如何在C++中分多次读取文件直到EOF

13

所以,这是我的问题:我想制作一个程序,从文件中读取数据块。假设每个块有1024个字节。 我读取了前1024个字节,执行各种操作,然后打开下一个1024个字节,而不读取旧数据。该程序应继续读取数据,直到达到EOF。

我目前正在使用以下代码:

std::fstream fin("C:\\file.txt");

vector<char> buffer (1024,0); //reads only the first 1024 bytes
fin.read(&buffer[0], buffer.size());

但是我该如何读取接下来的1024个字节呢?我想使用一个for循环来实现,但我真的不知道该怎么做。我完全是C++的新手,所以如果有人能帮助我,那就太好了。谢谢!


http://www.cplusplus.com/reference/fstream/fstream/rdbuf/ - user2485710
3
是的,使用循环是比较好的方法。此外,您应该使用“fin.gcount()”来确定实际读取了多少数据。如果您只是读取文件,则应使用“std::ifstream”(如果您想要读取二进制数据而不是文本,则应使用“std::ios_base::binary”打开文件)。 - Dietmar Kühl
4个回答

20

您可以使用循环来完成此操作:

std::ifstream fin("C:\\file.txt", std::ifstream::binary);
std::vector<char> buffer (1024,0); //reads only the first 1024 bytes

while(!fin.eof()) {
    fin.read(buffer.data(), buffer.size())
    std::streamsize s=fin.gcount();
    ///do with buffer
}

##EDITED

http://en.cppreference.com/w/cpp/io/basic_istream/read


@user2485710:对于初学者来说,正确使用它太难了。即使是有经验的用户也很少听说过std::istream::sentry - Dietmar Kühl
1
@user2485710,因为大多数人不想为了读取二进制文件而去翻阅iostreams文档。 - 111111
1
这真的有效吗?根据文档,“read”返回*this。 - Vink
5
应该这样写: while (!fin.eof()) { fin.read(buffer.data(), buffer.size()); std::streamsize dataSize = fin.gcount(); } - Vink
4
这是危险的代码 - 你应该继续使用while(fin.good()),因为只有在到达文件末尾时才会设置eof; 如果发生错误,您的循环将永远继续。当文件结束或者设置了 badbit 时,good 将变为 false。此外,在循环结束后,您应该测试if (fin.bad()),以查看是否出现了任何问题。 - Richard Whitehead
显示剩余3条评论

10

已被选中的答案对我无效 - 它不能读取最后一部分块。这个可以:

void readFile(std::istream &input, UncompressedHandler &handler) {
    std::vector<char> buffer (1024,0); //reads only 1024 bytes at a time
    while (!input.eof()) {
        input.read(buffer.data(), buffer.size());
        std::streamsize dataSize = input.gcount();
        handler({buffer.begin(), buffer.begin() + dataSize});
    }
}

这里UncompressedHandler接受std::string,因此我使用从两个迭代器构造的构造函数。


因为在上一次(不完整的)读取时,istream到达了eof并且评估为false,所以没有进入while循环体。 - MateuszL
我现在明白了,谢谢。对于其他人,请检查 https://en.cppreference.com/w/cpp/io/basic_istream/read 的返回值(返回流本身 *this)以及其 bool 方法的重载 https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool(如果 fail() 返回 true,则返回空指针)。当流达到结尾时,fail() 返回 true - Rick

1

我认为你错过了一个指针,它指向你在文件中最后访问的位置,这样当你第二次读取时,你不会从头开始,而是从你上次访问的最后一个点开始。

看一下这段代码:

std::ifstream fin("C:\\file.txt");
char buffer[1024]; //I prefer array more than vector for such implementation

fin.read(buffer,sizeof(buffer));//first read get the first 1024 byte

fin.read(buffer,sizeof(buffer));//second read get the second 1024 byte

那么你可能会如何考虑这个概念。


0

我认为那会起作用

     #include <stdlib.h>
     #include <stdio.h>
     #include <string.h>
     #include <fstream>
    
    // Buffer size 16 Megabyte (or any number you like)
    size_t buffer_size = 1 << 24; // 20 is 1 Megabyte
    char* buffer = new char[buffer_size];

    std::streampos fsize = 0;
    std::ifstream file("c:\\file.bin", std::ios::binary);

    fsize = file.tellg();
    file.seekg(0, std::ios::end);
    fsize = file.tellg() - fsize;

    int loops = fsize / buffer_size;
    int lastChunk = fsize % buffer_size;

    for (int i = 0; i < loops; i++) {
        file.read(buffer, buffer_size);
        // DO what needs with the buffer
    }

    if (lastChunk > 0) {
        file.read(buffer, lastChunk);
        // DO what needs with the buffer
    }

    delete[] buffer;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接