【问题标题】:Read large txt file in c++在 C++ 中读取大的 txt 文件
【发布时间】:2023-03-28 12:55:02
【问题描述】:

我想读取内存中大约 5MB 的文件... 该文件具有这种格式(它是一个文本文件)

ID 3:  0 itemId.1 0 itemId.2 0 itemId.5 1 itemId.7 ........................ 20 itemId.500
ID 50:  0 itemId.31 0 itemId.2 0 itemId.4 2 itemId.70 ........................ 20 itemId.2120
.....

如何在 c++ 中有效地做到这一点?

【问题讨论】:

  • 标准方式不够高效?
  • 你真的应该重新考虑你认为的“大”。估算是一种工程技能。
  • 一般情况下,根据平台不同,5MB 不算大。大多数 PC 可以将 5MB 的文件完全读入内存。

标签: c++ file format


【解决方案1】:

逐行读取文件:

ifstream fin ("file.txt");
string     myStr;

while(getline(fin, myStr))   // Always put the read in the while condition.
{                            // Then you only enter the loop if there is data to
    //use myStr data         // processes. Otherwise you need to read and then
}                            //  test if the read was OK
                             //
                             // Note: The last line read will read up to (but not
                             //        past) then end of file. Thus When there is
                             //        no data left in the file its state is still
                             //        OK. It is not until you try and explicitly
                             //        read past the end of file that EOF flag is set.

关于不明确调用 close 的原因,请参阅:
https://codereview.stackexchange.com/questions/540/my-c-code-involving-an-fstream-failed-review/544#544

如果效率是您的主要目标(可能不是)。然后将整个文件读入内存并从那里解析:见下面的 Thomas:Read large txt file in c++

【讨论】:

  • 如果你想在行中使用分隔符,你还会推荐这种方法吗?
  • @Shredder:您可以使用getline(fin, myStr, '#') 作为哈希分隔符等。但其他代码相同。
  • 显然呵呵。我想知道如果您想使用分隔符,是否将getline() 放在while 循环中仍然是可行的方法,因为您将在循环块中多次调用getline 以获取该行的其余数据。只是好奇
【解决方案2】:

将整个文件读入内存,然后处理内存中的内容。

当电机保持旋转时,文件资源(例如硬盘驱动器)效率最高。因此,1 次大数据读取比 5 次少量数据读取效率更高。

在大多数平台上,访问内存比访问文件要快。使用这些信息,可以通过将数据读入内存然后处理内存来提高程序的效率。

结合这两种技术将产生更高的性能:在一个事务中将尽可能多的数据读取到内存中,然后处理内存。

有些人声明charunsigned char 的大型数组(用于二进制数据)。其他人告诉 std::string 或 std::vector 保留大量内存,然后将数据读入数据结构。

此外,块读取(又名istream::read())将绕过 C++ 流工具的大部分慢速部分。

【讨论】:

    【解决方案3】:

    使用file stream

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    int main() {
        string line;
        ifstream myfile ("example.txt");
        if (myfile.is_open())
        {
            while ( getline(myfile, line) )
                cout << line << endl;
    
            myfile.close();
        }
        else 
        {
            cout << "Unable to open file"; 
        }
    
        return 0;
    }
    

    5MB 确实不是一个大文件。流会照顾你一次读取块,但真的;几乎任何运行它的机器都可能能够将 5MB 直接读取到内存中。

    【讨论】:

    • 这有多余的代码,会尝试读太多的一行代码。改为使用已建立的习语来阅读文本(在本例中为while (getline(myfile, line)))。
    • @Konrad:是的,我很懒,只是把它复制了出来。我想我应该修复它...谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 2020-10-09
    • 2017-08-31
    • 1970-01-01
    相关资源
    最近更新 更多