Размер файла больше, чем должен быть, добавляются дополнительные новые строки
ВСТУПЛЕНИЕ:
Я читаю из текстового файла с помощью ReadFile. Буфер, переданный в ReadFile, отправляется на стандартный вывод с помощью cout. Стандартный вывод перенаправляется в текстовый файл.
ПРОБЛЕМА:
Хотя мой код "работает", никакие данные не теряются, результирующий файл больше исходного.
При открытии в блокноте все кажется прекрасным, но при открытии в блокноте++ я отчетливо вижу добавленные дополнительные строки. Эти строки являются новыми строками (\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) { // '\0' terminate buffer, needed for cout only ::memset(buffer, '\0', sizeof(buffer)); if (!::ReadFile(hFile, buffer, sizeof(buffer) - 1, // - 1 for '\0', 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, но я не уверен.
Richard MacCutchan
Сколько дополнительных строк вы видите в выходном файле? Вполне возможно, что последний прочитанный блок не заполняет буфер, но когда вы отправляете его в std:: out, он содержит дополнительные новые строки. То, что вы делаете, - не лучший способ скопировать текстовый файл из одного места в другое.
MyOldAccount
Сколько дополнительных строк вы видите в выходном файле? Примерно 10% от размера файла. Изучив файл, я обнаружил, что файл заполнен \r\r\n вместо \n. Следующая ссылка, раздел двоичный и текстовый режимы, по-видимому, объясняет, почему: http://en.cppreference.com/w/cpp/io/c#Binary_and_text_modes
Richard MacCutchan
Да, потому что вы эффективно читаете его в двоичном режиме.
MyOldAccount
Я согласен, но тогда std::cout.write(buffer, bytesRead);
в моем примере кода должно работать, не так ли? Тем не менее, я получаю тот же результат. Это должна быть подробная информация о реализации, указанная в ссылке... Я думаю ReadFile
должно быть в паре с WriteFile
в этом случае, так как только тогда я получаю правильный вывод...
Richard MacCutchan
Именно так. Как я уже говорил, ReadFile
читает файл в байтовом режиме (эффективно читает в двоичном), поэтому символы новой строки не интерпретируются.