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

相关推荐
不会代码的小猴7 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
青瓦梦滋7 小时前
传输层UDP/TCP协议
linux·网络·c++·网络协议·tcp/ip·udp
一只旭宝8 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
Lhan.zzZ10 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
zh路西法12 小时前
【3D SLAM源码解读系列】(二)Small_gicp——5 个积木搭出最优点云配准
c++·pcl·icp·fastgicp·smallgicp·gicp
fpcc13 小时前
ubuntu26环境下的开发环境安装处理
c++·并行编程
charlie11451419115 小时前
Cinux · 第一次跳进 Ring 3:用户态与特权隔离
开发语言·c++·操作系统·开源项目
别动我齐刘海15 小时前
机器学习基础2——C++、OpenCV、点云、Open3D
c++·人工智能·opencv·机器学习·计算机视觉·机器人·ros2
躺不平的理查德16 小时前
Windows C++ 第三方库使用流程备忘录--OpenCV
开发语言·c++
余额瞒着我当琳16 小时前
C++STL容器string--迭代器,string的接口,string的遍历,访问方式
c++