提问者:小点点

如何在C++中从头到尾写入文件


我有一个函数可以实时计算所需的结果(最终结果是大约50MB的只包含字符的文本文件),但顺序相反。

举例说明:我的函数将计算“5,4,3,2,1,。。。”,但我要求将“1,2,3,4,5”写入文件。

我想把它写到一个输出文件中,从头到尾都是动态的。

目前,我正在使用std::ofstream::binary缓冲,反转和写入文件,但是我需要减少相关的时间,更重要的是减少空间开销。

做这件事最有效率的方法是什么?

谢谢。

编辑:输出大小已知。


共2个答案

匿名用户

我明白你的要求是这样的:

  • 以二进制形式写入数据(尽管您刚才说的是文本文件)
  • 要存储纯字符
  • 您预先知道要写入的字符数
  • 然后在结尾处写入第一个元素,然后在前面写入一个元素,依此类推。

如果您确实不想使用缓冲区,那么您必须使用seekp。 但现在已经有一些暗示:这将是一个非常缓慢的解决方案。

反正怎么办? 所以:

  • 首先打开要输出的文件并检查它是否可以打开
  • 计算输出文件中最后一个字符的偏移量位置
  • 找这个位置写
  • 递减偏移量

Seek和write将如下所示

fileStream.seekp(offset--).put(testData[index]);

由于我没有你的计算功能,所以我创建了一些虚拟数据。 这需要你去适应。

请参阅以下示例片段:

#include <iostream>
#include <fstream>
#include <array>
#include <numeric>

// The known size of test data
constexpr size_t OutputSize = 50'000U;
// Some simple test data
static std::array<char, OutputSize> testData{};

int main() {

    // You will calculate the data in a different part of your code
    // I jsut fill the array with some data
    std::iota(testData.begin(), testData.end(), 0);

    // Open the file and check, if it could be opened.
    if (std::ofstream fileStream{ "r:\\test.bin", std::ofstream::binary }; fileStream) {

        // Caculate position offset of last element
        size_t offset{ (OutputSize - 1)};

        // Calculate and write data
        for (size_t index{}; index < OutputSize; ++index) {

            // Your claculation here
            // . . .

            // Seek and write data
            fileStream.seekp(offset--).put(testData[index]);
        }
    }
    return 0;
}

再来一次。 寻找是非常缓慢的。

匿名用户

实际上,从头到尾写文件是一个低效的解决方案,因为你会在文件预分配和查找上浪费一些时间。 最好只是从结束到开始再到文件写入数组。

我不知道你的程序是怎么写的,所以我的答案可能不是你想要的那么准确,但我假设它可以是这样做的:

#include <iostream>
#include <vector>
#include <ostream>
#include <fstream>


// Variant 1
void writeMyData(const std::vector<int>& data, std::ofstream& stream)
{
    for (auto it = data.rbegin(); it != data.rend(); it++)
        stream.write((const char*)&*it, sizeof(int));
}


// Variant 2
void writeMyData2(const int* data, int length, std::ofstream& stream)
{
    for (int i = length - 1; i >= 0; i--)
        stream.write((const char*)(data + i), sizeof(int));
}


int main()
{
    std::vector<int> yourBuffer = {5, 4, 3, 2, 1};
    std::ofstream file;
    file.open ("data.bin", std::ios::binary);
    
    // Write: 1, 2, 3, 4, 5
    // Variant 1
    writeMyData(yourBuffer, file);
    
    // Variant 2
    //writeMyData2(yourBuffer.data(), yourBuffer.size(), file); 
    
    file.close();
    return 0;
}

因此,您可以使用反向迭代器(RBEGINREND而不是BEGINEND)或仅以相反的顺序迭代循环。

更新:或者你可以在RAM中反转数据,然后一次性写入所有数据。 很可能,这将是最有效的方式。

std::reverse(std::begin(yourBuffer), std::end(yourBuffer));
stream.write((const char*)yourBuffer.data(), sizeof(int) * yourBuffer.size());

注意sizeof(int)-可能您有char或其他类型。

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(何在|c++|中|从头到尾|写入|文件)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?