【问题标题】:read and write file in chunks of bytes in c++在c ++中以字节块读取和写入文件
【发布时间】:2013-11-14 18:08:28
【问题描述】:

我到处搜索,但我似乎无法理解如何使用 ios::cur。我需要以 10 个字节的块读取整个文件,将这些字节写入缓冲区,然后将该缓冲区写入另一个文件。为此,我发送前 10 个字节,然后发送接下来的 10 个字节,依此类推。但是如何确保指针从上次迭代的位置开始?

char* data = 0;
int i = 0;
std::ifstream is("test.txt", std::ifstream::binary);

if (is)
{
    is.seekg(0, is.end);
    int size = is.tellg();

    cout << size << endl;

    ofstream obj;
    obj.open("new.txt");

    while (!is.eof())
    {
        for (; i <= size;)
        {
            is.seekg(i, is.beg);
            int sz = is.tellg();
            // cout<<sz<<endl;

            data = new char[sz + 1]; //  for the '\0'
            is.read(data, sz);

            data[sz] = '\0'; // set '\0' 
            cout << " data size: " << strlen(data) << "\n";
            cout << data;
            i = i + 10;
        }
        obj.close();
    }
}

【问题讨论】:

    标签: c++ file file-io seekg


    【解决方案1】:

    您不需要重新定位文件位置。

    每次读取操作后文件位置都会更新。

    您应该使用两个文件对象,一个用于输入,另一个用于输出。

    在这两种情况下,文件位置都会在每次读写操作后更新。

    编辑 1:简化示例

    #define BUFFER_SIZE 16
    unsigned char buffer[BUFFER_SIZE];
    //...
    while (input_file.read((char *)buffer, BUFFER_SIZE))
    {
      output_file.write((char *)buffer, BUFFER_SIZE);
    }
    

    如果 input_file 的位置在偏移量 0,那么在第一次读取后,文件位置将在 16。这可以通过以下方式验证:

    int read_file_position = input_file.tellg();  
    cout << "input file position: " << read_file_position << endl;
    while (input_file.read((char *)buffer, BUFFER_SIZE))
    {
      read_file_position = input_file.tellg();
      cout << "input file position: " << read_file_position << endl;
      output_file.write((char *)buffer, BUFFER_SIZE);
    }
    

    【讨论】:

    • 我有两个对象,"is" 用于读取,obj 用于写入。您能否详细说明“您不需要重新定位文件位置。每次读取操作后文件位置都会更新。”?在我粘贴的代码中,前 10 个字节不会被打印出来。我不明白这背后的原因。 :(
    • 查看我对答案的补充。
    【解决方案2】:

    我认为可以简化为:

    char* data = 0;
    int i = 0;
    int size = 0;
    int sz = 10;
    std::ifstream is("test.txt", std::ifstream::binary);
    std::ofstream obj;
    data = new char[sz+1];
    int read_sz = 0;
    
    if (is)
    {
        obj.open("new.txt");
        read_sz = is.tellg(); //we are at the beginning of the file now
        while (!is.eof())
        {
            int old_read_sz = read_sz; // old position - before next read
            is.read(data, sz);
            read_sz = is.tellg(); // new position, we've read read_sz-old_read_sz bytes
            data[read_sz-old_read_sz] = '\0'; // set '\0'
            // I hope you wanted the two lines below only for debugging purposes :)
            cout << " data size so far: " << read_sz << "\n";
            cout << data << endl;
            obj.write(data, read_sz-old_read_sz);
         }
        obj.close();
        is.close();
        cout << "total data size: "<< read_sz << endl;
    }
    

    一旦你读取了一个数据块,你的文件光标已经移过了那个块,所以你不需要自己重新定位它(从当前位置移动到结束/开始和返回可能代价高昂 - 时间上 -特别是如果你有一个大的输入文件)。

    顺便说一下,这里有一个关于该主题的教程:http://www.cplusplus.com/doc/tutorial/files/

    更新:忘记了 is.read() != old C-style read :-}

    【讨论】:

    • 数据=新字符[sz+1]; // 为0生成调试输出(其实std::string(data, read_sz)会更好)
    • 哦,确实是这个意图 - 已修复 :)
    • 哇哦。是的,那是为了调试。但是,我收到此错误:“无法从 'class std::basic_istream >' 转换为 'int'” 在“int read_sz = is.read(data, sz );"。你能告诉我 read_sz 在做什么吗?
    • 将“int read_sz = ...”替换为“...; int read_sz = is.gcount();”
    • 天啊,它现在可以工作了!谢谢 :D 但是我读到的所有关于发送数据字节到字节的地方都包括 seekg 和 tellg() 调用。他们在 C++ 中被推荐吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多