Click here to Skip to main content
15,887,746 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
INTRODUCTION:

I am reading from text file with ReadFile. Buffer passed to ReadFile is sent to standard output with cout. Standard output is redirected to a text file.

PROBLEM:

Although my code "works", no data is lost, resulting file is larger than the original one.

When opened in notepad, everything seems fine, but when opened in Notepad++ I can clearly see extra lines added. These lines are new lines (\n).

MVCE that reproduces this behavior is submitted below.

C++
#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;
}


QUESTION:

What is causing above described behavior? How to fix it?

What I have tried:

As I type this post I am Googling aimlessly, hoping for some clue to show up.

I suspect that the problem lies when outputting \n, it seems that Windows inserts \r as well, but I am not sure.
Posted
Updated 3-Dec-16 0:25am
Comments
Richard MacCutchan 5-Nov-16 5:37am    
How many extra lines are you seeing in the output file? It is quite possible that the last block read is not filling the buffer, but when you send that to std::out it contains extra newlines. What you are doing is not the best way to copy a text file from one place to another.
MyOldAccount 5-Nov-16 6:42am    
How many extra lines are you seeing in the output file? Roughly 10% of the file size. After examining file, I have found out that file is filled with \r\r\n instead with \n. The following link, section Binary and text modes, seems to explain why: http://en.cppreference.com/w/cpp/io/c#Binary_and_text_modes
Richard MacCutchan 5-Nov-16 6:43am    
Yes, because you are effectively reading it in binary mode.
MyOldAccount 5-Nov-16 7:21am    
I agree, but then std::cout.write(buffer, bytesRead); in my code example should work, right? Still, I get the same result. It must be implementation detail stated in the link... I guess ReadFile must be paired with WriteFile in this case, since only then I get the correct output...
Richard MacCutchan 6-Nov-16 2:45am    
Exactly so. As I said before, ReadFile is reading the file in byte mode (effectively reading in binary), so newline characters are not interpreted.

1 solution

The cause of the following problem, as far as I can understand the actually last call to ReadFile API function. Actually during the last function call you read beyond the file.
 
Share this answer
 
Comments
Richard MacCutchan 3-Dec-16 7:19am    
Not true, see my last comment.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900