Чтение файла строка за строкой с помощью ifstream в C++
содержимое файла.txt-это:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
здесь 5 3
- это пара координат.
Как обрабатывать эти данные строка за строкой в C++?
Я могу получить первую строку, но как мне получить следующую строку файла?
ifstream myfile;
myfile.open ("text.txt");
7 ответов
во-первых, сделать ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
два стандартных метода:
-
предположим, что каждая строка состоит из двух чисел и прочитать маркер, маркер:
int a, b; while (infile >> a >> b) { // process pair (a,b) }
-
синтаксический анализ на основе строк, используя строковые потоки:
#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) }
вы не должны смешивать (1) и (2), так как синтаксический анализ на основе токенов не поглощает новые строки, поэтому вы можете получить ложные пустые строки, Если используете getline()
после извлечение на основе токенов уже привело вас к концу строки.
использовать ifstream
для чтения данных из файла:
std::ifstream input( "filename.ext" );
Если вам действительно нужно читать строку за строкой, то сделайте следующее:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
но вам, вероятно, просто нужно извлечь пары координат:
int x, y;
input >> x >> y;
обновление:
в вашем коде вы используете ofstream myfile;
, однако o
на ofstream
расшифровывается как output
. Если вы хотите прочитать из файла (ввода), используйте ifstream
. Если вы хотите читать и писать, использовать fstream
.
С вашими координатами принадлежат вместе, как пары, почему бы не написать структуру для них?
struct CoordinatePair
{
int x;
int y;
};
тогда вы можете написать перегруженный оператор извлечения для istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates)
{
is >> coordinates.x >> coordinates.y;
return is;
}
и затем вы можете прочитать файл координат прямо в вектор такой:
#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
}
расширение принятого ответа, если вход:
1,NYC
2,ABQ
...
вы все равно сможете применить такую же логику, как это:
#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();
чтение файла строка за строкой в C++ может быть сделано по-разному.
[быстрый] цикл с std:: getline ()
самый простой подход-открыть std::ifstream и цикл, используя вызовы std:: getline (). Код чистый и понятный.
#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] использование Boost's file_description_source
другая возможность-использовать библиотеку Boost, но код становится немного более подробным. Производительность очень похожа на код выше (цикл с 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();
}
}
}
[самый быстрый] используйте код C
если производительность имеет решающее значение для вашего программного обеспечения,вы можете рассмотреть возможность использования языка C. Этот код может быть в 4-5 раз быстрее, чем версии C++ выше, см. benchmark ниже
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 -- какой из них быстрее?
Я сделал несколько тестов производительности с кодом выше, и результаты интересны. Я протестировал код с файлами ASCII, которые содержат 100 000 строк, 1 000 000 строк и 10 000 000 строк текста. Каждая строка текста содержит в среднем 10 слов. Программа компилируется с помощью -O3
оптимизация и ее вывод перенаправляется в /dev/null
для того, чтобы удалить переменную времени регистрации из измерения. И последнее, но не менее важное: каждый фрагмент кода регистрирует каждую строку с printf()
функция для последовательности.
результаты показывают время (в МС), которое каждый кусок кода взял для чтения файлов.
производительность разница между двумя подходами на C++ минимальна и не должна иметь никакого значения на практике. Производительность кода C - это то, что делает бенчмарк впечатляющим и может быть игровым чейнджером с точки зрения скорости.
10K lines 100K lines 1000K lines
Loop with std::getline() 105ms 894ms 9773ms
Boost code 106ms 968ms 9561ms
C code 23ms 243ms 2397ms
хотя нет необходимости закрывать файл вручную, но это хорошая идея, чтобы сделать так, если область переменной файл больше:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
с аргументами командной строки:
#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);
}