文件及;CStdioFile在写入时产生不同的结果&;阅读

文件及;CStdioFile在写入时产生不同的结果&;阅读,file,visual-c++,mfc,cfile,File,Visual C++,Mfc,Cfile,据我所知,当使用typeBinary标志创建时,CFile和CStdioFile应该以相同的方式工作,除非后者缓冲数据,因此具有更好的性能 因此,我编写以下代码来确认这一点: ULONGLONG GetRand(ULONGLONG uMax) { UINT uValue; if (rand_s(&uValue) == 0) return (ULONGLONG)(((double)uValue / (double)UINT_MAX) * uMax);

据我所知,当使用typeBinary标志创建时,CFile和CStdioFile应该以相同的方式工作,除非后者缓冲数据,因此具有更好的性能

因此,我编写以下代码来确认这一点:

ULONGLONG GetRand(ULONGLONG uMax)
{
    UINT uValue;

    if (rand_s(&uValue) == 0)
        return  (ULONGLONG)(((double)uValue / (double)UINT_MAX) * uMax);
    else
        return  0;
}

void CheckOffset(CFile& File1, CFile& File2)
{
    ULONGLONG uOffset1, uOffset2;
    CString strMsg;

    uOffset1 = File1.GetPosition();
    uOffset2 = File2.GetPosition();

    if (uOffset1 != uOffset2)
    {
        strMsg.Format(_T("Difference offset. Offset1 = %I64u. Offset2 = %I64u."), uOffset1, uOffset2);
        AfxMessageBox(strMsg);
    }
}

void CheckLength(CFile& File1, CFile& File2)
{
    ULONGLONG uLength1, uLength2;
    CString strMsg;

    uLength1 = File1.GetLength();
    uLength2 = File2.GetLength();

    if (uLength1 != uLength2)
    {
        strMsg.Format(_T("Difference length. Length1 = %I64u. Length2 = %I64u."), uLength1, uLength2);
        AfxMessageBox(strMsg);
    }
}

void CheckSeek(CFile& File1, CFile& File2, ULONGLONG uOffset)
{
    ULONGLONG uOffset1, uOffset2;
    CString strMsg;

    uOffset1 = File1.Seek(uOffset, CFile::begin);
    uOffset2 = File2.Seek(uOffset, CFile::begin);

    if (uOffset1 != uOffset2)
    {
        strMsg.Format(_T("Difference seek results. Offset1 = %I64u. Offset2 = %I64u."), uOffset1, uOffset2);
        AfxMessageBox(strMsg);
    }
}

void CheckRead(CFile& File1, CFile& File2, UINT uSize)
{
    BYTE lpBuf1[4096], lpBuf2[4096];
    UINT uRead1, uRead2;
    CString strMsg;

    //  Read buffer from file1 & file2
    uRead1 = File1.Read(lpBuf1, uSize);
    uRead2 = File2.Read(lpBuf2, uSize);

    if ((uRead1 != uRead2) || (memcmp(lpBuf1, lpBuf2, uRead1) != 0))
    {
        strMsg.Format(_T("Difference read results. uRead1 = %u. uRead2 = %u."), uRead1, uRead2);
        AfxMessageBox(strMsg);
    }
}

void CTestStdioFile64Dlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here
    CFile File1;
    CStdioFile File2;
    UINT uSize;
    BYTE lpBuf[4096];
    CString strMsg;

    if (File1.Open(_T("F:\\Temp\\Test1.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive | CFile::typeBinary))
    {
        if (File2.Open(_T("F:\\Temp\\Test2.dat"), CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive | CFile::typeBinary))
        {
            CheckOffset(File1, File2);
            CheckLength(File1, File2);

            //  Write data
            for (UINT uIndex = 0; uIndex < 20000; uIndex ++)
            {
                //  Generate a randome size for write
                uSize = (UINT)GetRand(4096);

                //  Generate buffer with random data
                for (UINT j = 0; j < uSize; j++)
                    lpBuf[j] = (BYTE)GetRand(255);

                //  Write buffer to file1 & file2
                File1.Write(lpBuf, uSize);
                File2.Write(lpBuf, uSize);

                File1.Flush();
                File2.Flush();

                CheckOffset(File1, File2);
                CheckLength(File1, File2);

                //  Seek to a randome location
                CheckSeek(File1, File2, GetRand(File1.GetLength()));

                //  Generate a randome size for read
                uSize = (UINT)GetRand(4096);

                CheckRead(File1, File2, uSize);
                CheckOffset(File1, File2);
            }

            File2.Close();
        }

        File1.Close();
    }
}
ULONGLONG GetRand(ULONGLONG uMax)
{
单位价值;
如果(随机值(&U值)==0)
返回值(ULONGLONG)((双)uValue/(双)UINT_MAX)*uMax);
其他的
返回0;
}
无效校验偏移(CFile&File1、CFile&File2)
{
ULONGLONG uOffset1、uOffset2;
CString-strMsg;
uOffset1=File1.GetPosition();
uOffset2=File2.GetPosition();
如果(uOffset1!=uOffset2)
{
strMsg.Format(_T(“差分偏移量偏移量1=%I64u.偏移量2=%I64u”)、uOffset1、uOffset2);
AfxMessageBox(strMsg);
}
}
无效校验长度(CFile&File1、CFile&File2)
{
ULONGLONG uLength 1、uLength 2;
CString-strMsg;
ulenth1=File1.GetLength();
ulenth2=File2.GetLength();
如果(uLength 1!=uLength 2)
{
strMsg.Format(_T(“差分长度.长度1=%I64u.长度2=%I64u”)、uLength 1、uLength 2);
AfxMessageBox(strMsg);
}
}
无效检查寻道(CFile&File1、CFile&File2、ULONGLONG uOffset)
{
ULONGLONG uOffset1、uOffset2;
CString-strMsg;
uOffset1=File1.Seek(uOffset,CFile::begin);
uOffset2=File2.Seek(uOffset,CFile::begin);
如果(uOffset1!=uOffset2)
{
strMsg.Format(_T(“差分寻道结果.偏移量1=%I64u.偏移量2=%I64u”)、uOffset1、uOffset2);
AfxMessageBox(strMsg);
}
}
无效检查读取(CFile&File1、CFile&File2、UINT uSize)
{
字节lpBuf1[4096],lpBuf2[4096];
UINT uRead1、uRead2;
CString-strMsg;
//从文件1和文件2读取缓冲区
uRead1=File1.Read(lpBuf1,uSize);
uRead2=File2.Read(lpBuf2,uSize);
如果((uRead1!=uRead2)| |(memcmp(lpBuf1,lpBuf2,uRead1)!=0))
{
strMsg.Format(_T(“差异读取结果.uRead1=%u.uRead2=%u.”),uRead1,uRead2);
AfxMessageBox(strMsg);
}
}
void CTestStdioFile64Dlg::OnBnClickedButton1()
{
//TODO:在此处添加控件通知处理程序代码
文件1;
CStdioFile文件2;
单元使用;
字节lpBuf[4096];
CString-strMsg;
如果(文件1.Open(_T(“F:\\Temp\\Test1.dat”),CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive | CFile::typeBinary))
{
如果(文件2.Open(_T(“F:\\Temp\\Test2.dat”),CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive | CFile::typeBinary))
{
检查偏移量(文件1、文件2);
检查长度(文件1、文件2);
//写入数据
对于(UINT uIndex=0;uIndex<20000;uIndex++)
{
//为写入生成随机大小
uSize=(UINT)GetRand(4096);
//使用随机数据生成缓冲区
对于(UINT j=0;j
令我惊讶的是,在测试过程中,出现了许多CFileException,因为CStdioFile::Write将写出比预期更少的数据量

此外,还报告了许多不同的读取数据


为什么?

当我在调试模式下运行代码时,我得到以下断言

“在连续读写之间刷新。”, !流。是否有任何(\u IOREAD)

原因如下:

从C: (第306页,7.21.5.3)

以更新模式(“+”作为第二个或第三个)打开文件时 上述模式参数值列表中的字符),输入和 可以在相关联的流上执行输出。然而,产出 在没有中间调用的情况下,不得直接跟随输入 fflush功能或文件定位功能(fseek、fsetpos、, (或倒带),输入后不得直接输出 对文件定位函数的中间调用,除非输入 操作遇到endof文件

在代码中,在循环结束时调用
CheckRead
函数,但调用
File1.写入
File2.在下一次迭代中写入
,而不调用
fseek
/
刷新

作为快速修复,您可以在CheckRead函数的底部添加以下行:

File1.Seek(0, SEEK_CUR);
File2.Seek(0, SEEK_CUR);

非常感谢你。现在问题消失了。另外,由于CheckSeek函数也可以工作,所以我似乎不需要在写入后调用File1.Flush&File2.Flush。