如何逐行读取文件或一次性读取整个文本文件?

104

我正在学习一个关于文件操作的教程,其中包括如何从文件中读取和写入内容。

首先声明,这不是作业,只是我在寻求一般性的帮助。

我知道如何逐个单词地读取文件内容,但我不知道如何逐行或一次性读取整个文件。

如果我的文件包含1000个单词,逐个读取整个文件显然是不现实的。

我的文本文件名为“Read”,其内容如下:

I love to play games
I love reading
I have 2 books

目前为止,我已经完成了以下内容:

#include <iostream>
#include <fstream>

using namespace std;
int main (){
   
  ifstream inFile;
  inFile.open("Read.txt");

  inFile >>

有没有可能一次性读取整个文件,而不是逐行或逐个单词分开读取?


4
这里有明确的答案:https://dev59.com/TXRB5IYBdhLWcg3wr48U。 - sampson-chen
@Arkadiy,那是不正确的。对于一个100 MiB的文件,逐行读取将很容易花费几秒钟的时间,而每次读取4 KiB的块只需要不到一秒钟的时间。 - vallentin
@Vallentin:鉴于所有流都是缓冲的,实际的磁盘读取已经以块为单位完成。其余的只是在内存中操作数据。 - user3458
@Arkadiy,这很有趣,因为我昨天实际测试了速度。从最快到最慢的顺序是fread 4 KiBfread 128 bytesstd::getlinefgetcifstream::get。其中fread花费了0.15秒,而std::getline花费了6秒,对于一个1 GiB的文本文件。 - vallentin
@Arkadiy除了不断读取文件直到结束之外,没有对数据做任何处理。我需要类似于OP的东西,最终通过“fread 4 KiB”实现了这一点。它通过同时拥有2个块来工作。因此,如果单词(或者更好地说,最后一个单词)超过了第一个块,它将继续进入下一个块。所以是的,如果单词长度超过4 KiB,那么我将无法读取它。但对我来说,这并不是问题,我想限制任何复制和移动内存以保持速度,并且它有效(对于我的情况)。 - vallentin
显示剩余6条评论
9个回答

195

您可以使用 std::getline

#include <fstream>
#include <string>

int main() 
{ 
    std::ifstream file("Read.txt");
    std::string str; 
    while (std::getline(file, str))
    {
        // Process str
    }
}

还要注意的是最好在文件流的构造函数中使用文件名来构造文件流,而不是显式地打开它(关闭也一样,让析构函数来完成工作)。

有关 std::string::getline() 的更多文档可以阅读CPP Reference

可能读取整个文本文件的最简单方法就是连接这些检索到的行。

std::ifstream file("Read.txt");
std::string str;
std::string file_contents;
while (std::getline(file, str))
{
  file_contents += str;
  file_contents.push_back('\n');
}  

10
尽管不太明显,while(getline(f, line)) { ...} 确实是建议的做法。这在这里有解释:http://gehrcke.de/2011/06/reading-files-in-c-using-ifstream-dealing-correctly-with-badbit-failbit-eofbit-and-perror/ --- 在那里您还可以找到适当错误处理的有用方法。 - Dr. Jan-Philip Gehrcke
1
上述代码如果没有#include <iostream>将无法编译。 - Tyguy7
1
@Tyguy7 为什么需要 #include <iostream>?在我看来,<fstream><string> 就足够了。如果你指的是 std::getline,它在 <string> 中,而不是在 <iostream> 中。 - Fabio says Reinstate Monica
@FabioTurati 我不确定,但我知道一旦我包含它,所有的编译都很顺利。 - Tyguy7

24

我知道这是一个非常非常古老的帖子,但我也想指出另一种方法,它实际上非常简单... 这是一些示例代码:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {

    ifstream file("filename.txt");
    string content;

    while(file >> content) {
        cout << content << ' ';
    }
    return 0;
}

2
好的答案,我使用了stringstream而不是cout将整个文件读入一个巨大的stringstream。 - bjackfly

5

我认为你可以使用 istream .read() 函数。你可以使用合理的块大小循环,并直接读取到内存缓冲区,然后将其附加到某种任意的内存容器(例如 std::vector)中。我可以写一个示例,但我怀疑你不需要完整的解决方案;如果需要额外的信息,请告诉我。


我不知道是谁给这个答案点了踩,但这个答案很好。也许我不符合你的标准,但我使用的是同样的东西。 - agaonsindhe

4

嗯,要做到这一点,也可以使用C++中提供的freopen函数 - http://www.cplusplus.com/reference/cstdio/freopen/ 并按以下方式逐行读取文件:

#include<cstdio>
#include<iostream>

using namespace std;

int main(){
   freopen("path to file", "rb", stdin);
   string line;
   while(getline(cin, line))
       cout << line << endl;
   return 0;
}

4
上述解决方案不错,但“一次性读取文件”的更好解决方案如下:
fstream f(filename);
stringstream iss;
iss << f.rdbuf();
string entireFile = iss.str();

2

你好兄弟,这是一种使用以下代码在确切行中读取字符串的方法。

希望这能帮到你!

#include <iostream>
#include <fstream>

using namespace std;


int main (){


    string text[1];
    int lineno ;
    ifstream file("text.txt");
    cout << "tell me which line of the file you want : " ;
    cin >> lineno ; 



    for (int i = 0; i < lineno ; i++)
    {
        
        getline(file , text[0]);

    }   

    cout << "\nthis is the text in which line you want befor  :: " << text[0] << endl ;
    system("pause");

    return 0;
}

Good luck !


1

还有一种方法尚未提到,那就是std::vector

std::vector<std::string> line;

while(file >> mystr)
{
   line.push_back(mystr);
}

然后,您可以简单地迭代向量并修改/提取所需内容。


4
“vector”是一个不必要的步骤。您可以使用“std::istream_iteratorstd::string(inFile)”迭代遍历“ifstream”。 - Joseph Mansfield

1
你也可以使用这个来逐行读取文件中的所有行,然后打印i。
#include <iostream>
#include <fstream>

using namespace std;



bool check_file_is_empty ( ifstream& file){
    return file.peek() == EOF ;
}

int main (){


    string text[256];
    int lineno ;
    ifstream file("text.txt");
    int num = 0;

    while (!check_file_is_empty(file))
    {    
        getline(file , text[num]);
        num++;
    }
    for (int i = 0; i < num ; i++)
    {
        cout << "\nthis is the text in " <<  "line " << i+1 << " :: " << text[i] << endl ;


    }
    
    system("pause");

    return 0;
}

希望这能帮到你:)

-1
以下代码片段将帮助您读取包含Unicode字符的文件。
CString plainText="";
errno_t errCode = _tfopen_s(&fStream, FileLoc, _T("r, ccs=UNICODE"));
    if (0 == errCode)
    {
        CStdioFile File(fStream);
        CString Line;
        while (File.ReadString(Line))
        {
            plainText += Line;
        }
    }
    fflush(fStream);
    fclose(fStream);

在读取完文件后,您应该始终关闭文件指针,否则会导致错误。


由于使用了CString,这个答案不具备可移植性。 - Michael Kotzjan
要使用CString,只需包含头文件atlstr.h #include<atlstr.h> - Sarath Govind

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