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");
7 answers
Najpierw zrób ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
Dwie standardowe metody to:
-
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) }
-
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ż.
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
.
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
}
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();
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
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();
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);
}
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