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源码中进行拷贝。问题得到解决。

相关推荐
一方热衷.3 小时前
YOLO26-Seg ONNXruntime C++/python推理
开发语言·c++·python
仰泳的熊猫5 小时前
题目2194:蓝桥杯2018年第九届真题-递增三元组
数据结构·c++·算法
2301_803554525 小时前
linux 以及 c++编程里对于进程,线程的操作
linux·运维·c++
小糯米6017 小时前
C++ 排序
c++·算法·排序算法
EverestVIP7 小时前
c++前置声明的方式与说明
开发语言·c++
老约家的可汗8 小时前
C++篇之类和对象下
java·开发语言·c++
Mr_WangAndy8 小时前
C++数据结构与算法_排序算法
c++·排序算法·基础排序·高级排序
Irissgwe9 小时前
C&C++内存管理
c语言·开发语言·c++·c++内存管理
玖釉-9 小时前
解密图形渲染的性能原罪 —— Draw Call
c++·windows·图形渲染