Using buffers to read from unknown size file

强颜欢笑 提交于 2019-12-23 09:32:17

问题


I'm trying to read blocks from a file and I have a problem.

char* inputBuffer = new char[blockSize]
while (inputFile.read(inputBuffer, blockSize)) {
    int i = inputFile.gcount();
//Do stuff
}

Suppose our block size is 1024 bytes, and the file is 24,3 KiB. After reading the 23rd block, there will be 0,3 KiB left to read. I also want to read that 0,3 KiB, in fact I use gcount() later so I can know how much of the buffer did read(...) modify (in case if it is less).
But when it accesses the 24th block, read(...) returns a value such that the program does not enter the loop, obviously because the size of the remaining unread bytes in the file is less than the buffer size. What should I do?


回答1:


I think that Konrad Rudolf who you talk about in the comment to another answer makes a good point about the problem with reading until eof. If you never reach eof because of some other error you are in an infinite loop. So take his advice, but modify it to address the problem you have identified. One way of doing it is as follows;

bool okay=true;
while ( okay ) {
    okay = inputFile.read(inputBuffer, blockSize);
    int i = inputFile.gcount();
    if( i ) {
        //Do stuff
    }
}

Edit: Since my answer has been accepted, I am editing it to be as useful as possible. It turns out my bool okay is quite unnecessary (see ferosekhanj's answer). It is better to test the value of inputFile directly, that also has the advantage that you can elegantly avoid entering the loop if the file did not open okay. So I think this is the canonical solution to this problem;

inputFile.open( "test.txt", ios::binary );
while ( inputFile ) {
    inputFile.read( inputBuffer, blockSize );
    int i = inputFile.gcount();
    if( i ) {
        //Do stuff
    }
}

Now the last time you //Do stuff, i will be less than blockSize, except in the case that the file happens to be a multiple of blockSize bytes long.

Konrad Rudolf's answer here is also good, it has the advantage that .gcount() is only called once, outside the loop, but the disadvantage that it really needs data processing to be put in a separate function, to avoid duplication.




回答2:


The solution @Konrad Rudolph mentioned is to check for the stream object itself since that includes checking for eof and error condition. The inputFile.read() returns the stream that is inputFile itself so you can write like

while(inputFile.read())

But this will not work always. The case where it fails is your case. A proper solution would be to write like below

char* inputBuffer = new char[blockSize]
while (inputFile) 
{
    inputFile.read(inputBuffer, blockSize);
    int count = inputFile.gcount();
    //Access the buffer until count bytes
    //Do stuff
}

I think this was the solution what @Konrad Rudolph meant in his post. From my old CPP experience I also would do something like above.




回答3:


But when it accesses the 24th block, read(...) returns a value such that the program does not enter the loop, obviously because the size of the remaining unread bytes in the file is less than the buffer size.

That's because your loop is wrong. You should be doing:

while(!inputFile) {
    std::streamsize numBytes = inputFile.readsome(inputBuffer, blockSize);
//Do stuff
}

Notice the use of readsome instead of read.



来源:https://stackoverflow.com/questions/6449198/using-buffers-to-read-from-unknown-size-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!