使用缓冲区读取未知大小的文件

时间:2011-06-23 04:02:48

标签: c++ file-io buffer

我正在尝试从文件中读取块,但我遇到了问题。

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

假设我们的块大小为1024 bytes,文件为24,3 KiB。阅读第23个区块后,将会有0,3 KiB个阅读。我还想阅读0,3 KiB,事实上我稍后使用gcount()因此我可以知道有多少缓冲区read(...)修改了(如果它更少)。
 但是当它访问第24个块时,read(...)返回一个值,使程序不进入循环,显然是因为文件中剩余未读字节的大小小于缓冲区大小。我该怎么办?

3 个答案:

答案 0 :(得分:3)

我认为你在另一个答案的评论中谈到的康拉德鲁道夫(Konrad Rudolf)对阅读问题提出了一个很好的观点。如果由于某些其他错误而永远不会达到eof,那么您将处于无限循环中。所以请听取他的意见,但要对其进行修改以解决您发现的问题。一种方法如下;

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

编辑:由于我的答案已被接受,我正在编辑它以尽可能有用。事实证明我的bool没关系是完全没必要的(参见ferosekhanj的回答)。最好直接测试inputFile的值,还有一个优点,即如果文件没有打开就可以优雅地避免进入循环。所以我认为这是解决这个问题的规范解决方案;

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

现在你最后一次//做东西,我会比blockSize小,除非文件恰好是blockSize字节长的倍数。

Konrad Rudolf的回答here也很好,它的优点是.gcount()只在循环外调用一次,但缺点是它确实需要将数据处理放在一个单独的函数中,避免重复。

答案 1 :(得分:3)

@Konrad Rudolph提到的解决方案是检查流对象本身,因为这包括检查eof和错误条件。 inputFile.read()返回inputFile本身的流,因此您可以像

一样编写
while(inputFile.read())

但这总是不起作用。它失败的情况就是你的情况。一个合适的解决方案就是写下面的

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

我认为这是@Konrad Rudolph在帖子中所说的解决方案。根据我以前的CPP经验,我也会做类似的事情。

答案 2 :(得分:1)

  

但是当它访问第24个块时,read(...)返回一个值,使程序不进入循环,显然是因为文件中剩余未读字节的大小小于缓冲区大小。 / p>

那是因为你的循环错了。你应该这样做:

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

请注意使用readsome代替read