文件大小大于应有的大小,将添加额外的新行
File size is larger than it should, extra new lines are added
简介:
我正在用ReadFile读取文本文件。传递到ReadFile
的缓冲区被发送到具有cout的标准输出。标准输出被重定向到文本文件。
问题:
虽然我的代码"有效",但没有数据丢失,生成的文件比原始文件大。
当在记事本中打开时,一切似乎都很好,但当在notepad++中打开时我可以清楚地看到添加了额外的行。这些线是新的线(n
(。
下面提交了再现此行为的MVCE。
#include <iostream>
#include <Windows.h>
int main()
{
HANDLE hFile = ::CreateFile("C:\123.txt",
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
return ::GetLastError();
char buffer[256];
DWORD bytesRead = 1, // dummy value so while loop can work
bytesWritten = 0; // needed for WriteFile, not for cout version
//======== so WriteFile outputs to console, not needed for cout version
HANDLE hStandardOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == hStandardOutput)
{
std::cout << "GetStdHandle error code = " << ::GetLastError() << std::endl;
::CloseHandle(hFile);
return ::GetLastError();
}
//============================
while(bytesRead)
{
// ' ' terminate buffer, needed for cout only
::memset(buffer, ' ', sizeof(buffer));
if (!::ReadFile(hFile,
buffer,
sizeof(buffer) - 1, // - 1 for ' ', not needed when using WriteFile
&bytesRead, NULL))
{
std::cout << "ReadFile error code = " << ::GetLastError() << std::endl;
break;
}
/*============= Works fine
if(!::WriteFile(hStandardOutput, buffer, bytesRead, &bytesWritten, NULL))
{
std::cout << "WriteFile error code = " << ::GetLastError() << std::endl;
break;
}*/
//------------- comment out when testing WriteFile
std::cout << buffer; // extra lines...
// std::cout.write(buffer, bytesRead); // extra lines as well...
//----------------------------------------
}
::CloseHandle(hFile);
return 0;
}
问题:
是什么导致了上述行为?如何修复?
我为解决问题所做的努力:
当我输入这篇文章时,我在谷歌上漫无目的地搜索,希望能找到一些线索。
我怀疑问题出在输出n
时,Windows似乎也插入了r
,但我不确定。
n
字符对STL字符流具有特殊意义。它表示一条换行符,在输出时会被转换为特定于平台的换行符。此处讨论:
二进制和文本模式
文本流是由行组成的有序字符序列(零个或多个字符加上终止的
'n'
(。最后一行是否需要终止'n'
由实现定义。输入和输出时可能需要添加、更改或删除字符,以符合操作系统中表示文本的约定(特别是,Windows操作系统上的C流在输出时将n
转换为rn
,在输入时将rn
转换为n
(。
因此,很可能std::cout
在被赋予n
时输出rn
,即使之前的r
也被赋予,因此rn
的输入在输出时可以变成rrn
。在Windows上,单个应用程序如何处理裸露的CR字符并不是标准行为。它们可能被忽略,也可能被视为换行符。在你的情况下,听起来像是后者。
没有标准方式在二进制模式中使用std::cout
,因此n
被输出为n
而不是rn
。但是,请参阅如何使cout在二进制模式下运行?了解在Windows上以二进制模式输出std::cout
的一些可能方法,具体取决于编译器和STL实现。或者,您可以尝试使用std::cout.rdbuf()
来替换自己的std::basic_streambuf
对象,该对象执行到控制台的二进制输出。
也就是说,你的代码处理数据缓冲区的方式有点偏离,它应该看起来更像这样(不考虑以上信息(:
#include <iostream>
#include <Windows.h>
int main()
{
HANDLE hFile = ::CreateFile("C:\123.txt",
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE, // why??
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
return ::GetLastError();
char buffer[256];
DWORD bytesRead, bytesWritten, err;
//======== so WriteFile outputs to console, not needed for cout version
HANDLE hStandardOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (INVALID_HANDLE_VALUE == hStandardOutput)
{
err = ::GetLastError();
std::cout << "GetStdHandle error code = " << err << std::endl;
::CloseHandle(hFile);
return err;
}
//============================
do
{
if (!::ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL))
{
err = ::GetLastError();
std::cout << "ReadFile error code = " << err << std::endl;
::CloseHandle(hFile);
return err;
}
if (bytesRead == 0) // EOF reached
break;
/*============= Works fine
if (!::WriteFile(hStandardOutput, buffer, bytesRead, &bytesWritten, NULL))
{
err = ::GetLastError();
std::cout << "WriteFile error code = " << err << std::endl;
::CloseHandle(hFile);
return err;
}
*/
//------------- comment out when testing WriteFile
std::cout.write(buffer, bytesRead);
//----------------------------------------
}
while (true);
::CloseHandle(hFile);
return 0;
}
- 添加新行时工作代码引发异常.调试技巧?
- 取消脱壳:使用模板在多行类型定义中添加一个尖括号后的新行
- QML ListView将新行添加到模型中的子向量
- 如何防止 clang 格式向新行添加单个分号
- C++ 入门第 5 版第 17.5.3 章 fstream 没有添加新行
- 拆分后向 Qstring 添加新行
- 冻结向网格添加新行(wxwidgets)
- 将新行字符 () 添加到 CSV 文件中
- C++打印矢量添加新行
- QTableView 滚动到新添加的行
- C++如果未打开,则在文件末尾添加新行
- 使用 CPP 在之后添加新行的动态分配
- 如何在向量的向量开头添加新行
- 字符串流在转换int型时添加新行
- 添加新的行datagridview
- 文件大小大于应有的大小,将添加额外的新行
- 如何检测新行并将其添加到字符串中.Fstream
- 如何向现有的QTableWidget添加新行
- 我如何添加新的行到现有的QTablewidget
- 如何使用非托管C++向 Excel 文件添加新行