To my understanding, when creating with typeBinary flag, CFile & CStdioFile should works indentically, except the latter is buffering the data so has a better performance.
So I write the following codes to confirm this:
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();
}
}
To my surprise, in the test process, there are many CFileException raised because CStdioFile::Write will write out less amount of data than expected.
Also there are many different read data reported.
Why?