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