VS2022的MFC的ReadString的问题

用vs2022CStdioFile类读取文件时,当文件中出现有一段0,不是字符串0而是16进制0,会导致直接读取结束,但实际文件还有很长,则后面的内容无法读入。

因为之前用过vc6的同样的函数ReadString进行读取是没有问题的。因此问题肯定出现在这个函数上。

将VS2022的ReadString的函数拷贝出如下:

复制代码
BOOL CStdioFile::ReadString(CString& rString)
{
ASSERT_VALID(this);
rString = _T("");    // empty string without deallocating
const int nMaxSize = 128;
LPTSTR lpsz = rString.GetBuffer(nMaxSize);
LPTSTR lpszResult;
int nLen = 0;
for (;;)
{
    lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
    rString.ReleaseBuffer();

    // handle error/eof case
    if (lpszResult == NULL && !feof(m_pStream))
    {
        Afx_clearerr_s(m_pStream);
        AfxThrowFileException(CFileException::genericException, _doserrno,
            m_strFileName);
    }

    // if string is read completely or EOF
    if (lpszResult == NULL ||
        (nLen = AtlStrLen(lpsz)) < nMaxSize ||
        lpsz[nLen-1] == '\n')
        break;

    nLen = rString.GetLength();
    lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
}

// remove '\n' from end of string if present
lpsz = rString.GetBuffer(0);
nLen = rString.GetLength();
if (nLen != 0 && lpsz[nLen-1] == '\n')
    rString.GetBufferSetLength(nLen-1);

return nLen != 0;

}

代码来源:C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\atlmfc\src\mfc\filetxt.cpp

VC6的对应函数源码:

复制代码
BOOL CStdioFile::ReadString(CString& rString)
{
ASSERT_VALID(this);
rString = &afxChNil;    // empty string without deallocating
const int nMaxSize = 128;
LPTSTR lpsz = rString.GetBuffer(nMaxSize);
LPTSTR lpszResult;
int nLen = 0;
for (;;)
{
    lpszResult = _fgetts(lpsz, nMaxSize+1, m_pStream);
    rString.ReleaseBuffer();

    // handle error/eof case
    if (lpszResult == NULL && !feof(m_pStream))
    {
        clearerr(m_pStream);
        AfxThrowFileException(CFileException::generic, _doserrno,
            m_strFileName);
    }

    // if string is read completely or EOF
    if (lpszResult == NULL ||
        (nLen = lstrlen(lpsz)) < nMaxSize ||
        lpsz[nLen-1] == '\n')
        break;

    nLen = rString.GetLength();
    lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
}

// remove '\n' from end of string if present
lpsz = rString.GetBuffer(0);
nLen = rString.GetLength();
if (nLen != 0 && lpsz[nLen-1] == '\n')
    rString.GetBufferSetLength(nLen-1);

return lpszResult != NULL;

}

经过对比,可以发现

原来最后的判断不同了,VS2022是判断指针是否为0(return lpszResult != NULL;),VC6是判断字符串长度是否为0(return nLen != 0;)

若是正常的文本,中间不会出现二进制0的。

但在处理异常情况下,VC6的函数就要优一些,至于为何VS2022的函数要这样修改,我还没有搞明白。

但现在我要处理的文件中有16进制0,文件又需要全部读完,用VS2022的函数就行。退回用VC6又不现实。

最后解决办法是,继承CStdioFile类,重写ReadString函数,或增加一个ReadString函数(改个名)。使用的函数内容从VC6的MFC源码中进行拷贝。问题得到解决。

相关推荐
同学小张1 小时前
【端侧AI 与 C++】1. llama.cpp源码编译与本地运行
开发语言·c++·aigc·llama·agi·ai-native
爱学习的小邓同学5 小时前
C++ --- 多态
开发语言·c++
招摇的一半月亮12 小时前
P2242 公路维修问题
数据结构·c++·算法
f***019313 小时前
CC++链接数据库(MySQL)超级详细指南
c语言·数据库·c++
合方圆~小文13 小时前
球型摄像机作为现代监控系统的核心设备
java·数据库·c++·人工智能
椰萝Yerosius14 小时前
[题解]2024CCPC郑州站——Z-order Curve
c++·算法
滨HI017 小时前
C++ opencv简化轮廓
开发语言·c++·opencv
学习路上_write17 小时前
FREERTOS_互斥量_创建和使用
c语言·开发语言·c++·stm32·单片机·嵌入式硬件
闻缺陷则喜何志丹18 小时前
【SOSDP模板 容斥原理 逆向思考】3757. 有效子序列的数量|分数未知
c++·算法·力扣·容斥原理·sosdp·逆向思考
BestOrNothing_201519 小时前
一篇搞懂 C++ 重载:函数重载 + 运算符重载,从入门到会用(含 ++、<<、== 实战)
c++·函数重载·运算符重载·operator·前置后置++·重载与重写