Читайте файл построчно, используя ifstream в С++
Содержимое файла file.txt:
5 3
6 4
7 1
10 5
11 6
12 3
12 4
Где 5 3
- координатная пара. Как мне обрабатывать эти данные построчно в C++?
Я могу получить первую строку, но как мне получить следующую строку файла?
ifstream myfile;
myfile.open ("text.txt");
Ответы
Ответ 1
Сначала сделайте 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()
после того, как извлечение на основе токена вы уже до конца строки.
Ответ 2
Используйте ifstream
для чтения данных из файла:
std::ifstream input( "filename.ext" );
Если вам действительно нужно читать строки за строкой, сделайте следующее:
for( std::string line; getline( input, line ); )
{
...for each line in input...
}
Но вам, вероятно, просто нужно извлечь координатные пары:
int x, y;
input >> x >> y;
Update:
В вашем коде вы используете ofstream myfile;
, однако o
в ofstream
означает output
. Если вы хотите прочитать из файла (ввод), используйте ifstream
. Если вы хотите как читать, так и писать, используйте fstream
.
Ответ 3
Чтение файла построчно в 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();
}
[Быстрый] Использовать Boost 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
Если производительность важна для вашего программного обеспечения, вы можете рассмотреть возможность использования языка Си. Этот код может быть в 4-5 раз быстрее, чем версии C++ выше, см. Тест ниже
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);
Тест - какой из них быстрее?
Я сделал несколько тестов производительности с кодом выше, и результаты интересны. Я проверил код с файлами 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
![enter image description here]()
Ответ 4
Так как ваши координаты принадлежат друг другу как пары, почему бы не написать для них структуру?
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
}
Ответ 5
Расширение принятого ответа, если вход:
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();
Ответ 6
Этот ответ предназначен для Visual Studio 2017, и если вы хотите прочитать из текстового файла, какое расположение относительно вашего скомпилированного консольного приложения.
сначала поместите ваш текстовый файл (в нашем случае test.txt) в папку вашего решения. После компиляции сохраните текстовый файл в той же папке с applicationName.exe
C:\Users\"Имя пользователя"\источник\\ "Repos solutionName"\"solutionName"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
// open the file stream
inFile.open(".\\test.txt");
// check if opening a file failed
if (inFile.fail()) {
cerr << "Error opeing a file" << endl;
inFile.close();
exit(1);
}
string line;
while (getline(inFile, line))
{
cout << line << endl;
}
// close the file stream
inFile.close();
}
Ответ 7
Это общее решение для загрузки данных в программу C++ и использует функцию readline. Это может быть изменено для файлов CSV, но разделитель здесь - пробел.
int n = 5, p = 2;
int X[n][p];
ifstream myfile;
myfile.open("data.txt");
string line;
string temp = "";
int a = 0; // row index
while (getline(myfile, line)) { //while there is a line
int b = 0; // column index
for (int i = 0; i < line.size(); i++) { // for each character in rowstring
if (!isblank(line[i])) { // if it is not blank, do this
string d(1, line[i]); // convert character to string
temp.append(d); // append the two strings
} else {
X[a][b] = stod(temp); // convert string to double
temp = ""; // reset the capture
b++; // increment b cause we have a new number
}
}
X[a][b] = stod(temp);
temp = "";
a++; // onto next row
}
Ответ 8
Хотя нет необходимости закрывать файл вручную, но это хорошая идея, если область действия переменной файла больше:
ifstream infile(szFilePath);
for (string line = ""; getline(infile, line); )
{
//do something with the line
}
if(infile.is_open())
infile.close();
Ответ 9
с аргументами командной строки:
#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);
}