Odczyt pliku linia po linii za pomocą ifstream w C++

Zawartość pliku.txt to:

5 3
6 4
7 1
10 5
11 6
12 3
12 4

Gdzie 5 3 jest parą współrzędnych. Jak przetwarzać dane linia po linii w C++?

Jestem w stanie uzyskać pierwszą linię, ale jak uzyskać następną linię pliku?

ifstream myfile;
myfile.open ("text.txt");
Author: jww, 2011-10-24

7 answers

Najpierw zrób ifstream:

#include <fstream>
std::ifstream infile("thefile.txt");

Dwie standardowe metody to:

  1. Załóżmy, że każda linia składa się z dwóch liczb i odczytaj token po tokenie:

    int a, b;
    while (infile >> a >> b)
    {
        // process pair (a,b)
    }
    
  2. Parsowanie liniowe, przy użyciu strumieni łańcuchowych:

    #include <sstream>
    #include <string>
    
    std::string line;
    while (std::getline(infile, line))
    {
        std::istringstream iss(line);
        int a, b;
        if (!(iss >> a >> b)) { break; } // error
    
        // process pair (a,b)
    }
    

Nie powinieneś mieszać (1) i (2), ponieważ parsowanie oparte na tokenie nie pochłania nowych linii, więc możesz skończyć z fałszywymi pustymi liniami, jeśli użyjesz getline() po ekstrakcji opartej na tokenie doprowadzi Cię do końca linii już.

 709
Author: Kerrek SB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-28 06:57:55

Użyj ifstream aby odczytać dane z pliku:

std::ifstream input( "filename.ext" );

Jeśli naprawdę potrzebujesz czytać wiersz po wierszu, zrób to:

for( std::string line; getline( input, line ); )
{
    ...for each line in input...
}

Ale prawdopodobnie wystarczy wyodrębnić pary współrzędnych:

int x, y;
input >> x >> y;

Update:

W kodzie używasz ofstream myfile;, jednak o w ofstream oznacza output. Jeśli chcesz odczytać z pliku (input) użyj ifstream. Jeśli chcesz zarówno czytać, jak i pisać, użyj fstream.

 142
Author: K-ballo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-07 18:04:10

Skoro twoje współrzędne należą do siebie jako pary, dlaczego nie napisać dla nich struktury?

struct CoordinatePair
{
    int x;
    int y;
};

Wtedy możesz napisać przeciążony operator ekstrakcji dla strumieni:

std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
    is >> coordinates.x >> coordinates.y;

    return is;
}

I wtedy możesz odczytać plik współrzędnych prosto do wektora takiego jak:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    char filename[] = "coordinates.txt";
    std::vector<CoordinatePair> v;
    std::ifstream ifs(filename);
    if (ifs) {
        std::copy(std::istream_iterator<CoordinatePair>(ifs), 
                std::istream_iterator<CoordinatePair>(),
                std::back_inserter(v));
    }
    else {
        std::cerr << "Couldn't open " << filename << " for reading\n";
    }
    // Now you can work with the contents of v
}
 8
Author: Martin Broadhurst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-20 16:58:07

Rozszerzenie na zaakceptowaną odpowiedź, jeśli Dane wejściowe to:

1,NYC
2,ABQ
...

Nadal będziesz w stanie zastosować tę samą logikę, w ten sposób:

#include <fstream>

std::ifstream infile("thefile.txt");
if (infile.is_open()) {
    int number;
    std::string str;
    char c;
    while (infile >> number >> c >> str && c == ',')
        std::cout << number << " " << str << "\n";
}
infile.close();
 5
Author: gsamaras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-25 22:18:44

Odczyt pliku linia po linii w C++ można wykonać na kilka różnych sposobów.

[Fast] Loop with std:: getline ()

Najprostszym podejściem jest otwarcie std:: ifstream i pętli za pomocą wywołań STD:: getline (). Kod jest czysty i łatwy do zrozumienia.

#include <fstream>

std::ifstream file(FILENAME);
if (file.is_open()) {
    std::string line;
    while (getline(file, line)) {
        // using printf() in all tests for consistency
        printf("%s", line.c_str());
    }
    file.close();
}

[Fast] użyj Boost ' S file_description_source

Inną możliwością jest użycie biblioteki Boost, ale kod staje się nieco bardziej gadatliwy. Wydajność jest dość podobna do powyższego kodu (pętla z std:: getline ()).

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <fcntl.h>

namespace io = boost::iostreams;

void readLineByLineBoost() {
    int fdr = open(FILENAME, O_RDONLY);
    if (fdr >= 0) {
        io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle);
        io::stream <io::file_descriptor_source> in(fdDevice);
        if (fdDevice.is_open()) {
            std::string line;
            while (std::getline(in, line)) {
                // using printf() in all tests for consistency
                printf("%s", line.c_str());
            }
            fdDevice.close();
        }
    }
}

[najszybszy] Użyj kodu C

Jeśli wydajność ma kluczowe znaczenie dla Twojego oprogramowania, możesz rozważyć użycie języka C. Ten kod może być 4-5 razy szybszy niż wersje C++ powyżej, zobacz benchmark poniżej

FILE* fp = fopen(FILENAME, "r");
if (fp == NULL)
    exit(EXIT_FAILURE);

char* line = NULL;
size_t len = 0;
while ((getline(&line, &len, fp)) != -1) {
    // using printf() in all tests for consistency
    printf("%s", line);
}
fclose(fp);
if (line)
    free(line);
Benchmark - który jest szybszy?

Zrobiłem kilka benchmarków wydajności z powyższym kodem i wyniki są interesujące. Testowałem kod z plikami ASCII, które zawierają 100 000 linii, 1 000 000 linii i 10 000 000 linii tekstu. Każda linijka tekstu zawiera średnio 10 słów. Program jest kompilowany z optymalizacją -O3, a jego wyjście jest przekazywane do /dev/null w celu usunięcia zmiennej logowania czasu z pomiaru. Na koniec, każdy fragment kodu loguje każdą linię za pomocą funkcji printf() dla spójności.

Wyniki pokazują czas (w ms), jaki każdy fragment kodu zajął na odczytanie plików.

Różnica w wydajności między dwoma podejściami C++ jest minimalna i nie powinna każda różnica w praktyce. Wydajność kodu C sprawia, że benchmark jest imponujący i może zmienić grę pod względem szybkości.

                             10K lines     100K lines     1000K lines
Loop with std::getline()         105ms          894ms          9773ms
Boost code                       106ms          968ms          9561ms
C code                            23ms          243ms          2397ms

Tutaj wpisz opis obrazka

 4
Author: HugoTeixeira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-31 02:03:02

Chociaż nie ma potrzeby ręcznego zamykania pliku, ale dobrym pomysłem jest to zrobić, jeśli zakres zmiennej file jest Większy:

    ifstream infile(szFilePath);

    for (string line = ""; getline(infile, line); )
    {
        //do something with the line
    }

    if(infile.is_open())
        infile.close();
 0
Author: Vijay Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 20:11:33

Z argumentami linii poleceń:

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include "print.h"

using namespace std;

int main (int argc, char *argv[]) 
{
    vector<string> list;
    ifstream in_stream;
    string line;
    in_stream.open(argv[1]);

    while(!in_stream.eof())
    {
        in_stream >> line;
        list.push_back(line);
    }
    in_stream.close();
    print(list);
    sort(list.begin(), list.end());
    print(list);
}
 -3
Author: Alex Spencer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-31 12:55:57