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

相关推荐
近津薪荼27 分钟前
dfs专题5——(二叉搜索树中第 K 小的元素)
c++·学习·算法·深度优先
xiaoye-duck29 分钟前
吃透 C++ STL list:从基础使用到特性对比,解锁链表容器高效用法
c++·算法·stl
_F_y34 分钟前
C++重点知识总结
java·jvm·c++
初願致夕霞2 小时前
Linux_进程
linux·c++
Thera7772 小时前
【Linux C++】彻底解决僵尸进程:waitpid(WNOHANG) 与 SA_NOCLDWAIT
linux·服务器·c++
Wei&Yan2 小时前
数据结构——顺序表(静/动态代码实现)
数据结构·c++·算法·visual studio code
wregjru3 小时前
【QT】4.QWidget控件(2)
c++
浅念-3 小时前
C++入门(2)
开发语言·c++·经验分享·笔记·学习
小羊不会打字3 小时前
CANN 生态中的跨框架兼容桥梁:`onnx-adapter` 项目实现无缝模型迁移
c++·深度学习
Max_uuc3 小时前
【C++ 硬核】打破嵌入式 STL 禁忌:利用 std::pmr 在“栈”上运行 std::vector
开发语言·jvm·c++