Odczyt całego pliku ASCII do C++ std:: string [duplikat]

to pytanie ma już odpowiedzi tutaj : Jak odczytać cały plik do std::string w C++? (15 odpowiedzi) Zamknięty 4 lata temu.

Muszę wczytać cały plik do pamięci i umieścić go w C++ std::string.

Gdybym miał to przeczytać do char[], odpowiedź byłaby bardzo prosta:

std::ifstream t;
int length;
t.open("file.txt");      // open input file
t.seekg(0, std::ios::end);    // go to the end
length = t.tellg();           // report location (this is the length)
t.seekg(0, std::ios::beg);    // go back to the beginning
buffer = new char[length];    // allocate memory for a buffer of appropriate dimension
t.read(buffer, length);       // read the whole file into the buffer
t.close();                    // close file handle

// ... Do stuff with buffer here ...

Teraz chcę zrobić dokładnie to samo, ale używając std::string zamiast char[]. Chcę unikać pętli, tzn. ja Nie chcę:

std::ifstream t;
t.open("file.txt");
std::string buffer;
std::string line;
while(t){
std::getline(t, line);
// ... Append line to buffer and go on
}
t.close()
Jakieś pomysły?
Author: animuson, 2010-04-08

9 answers

Update: okazuje się, że ta metoda, choć dobrze podąża za idiomami STL, jest w rzeczywistości zaskakująco nieefektywna! Nie rób tego z dużymi plikami. (Zobacz: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html )

Możesz utworzyć z pliku iterator streambuf i zainicjalizować nim łańcuch znaków:

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str((std::istreambuf_iterator<char>(t)),
                 std::istreambuf_iterator<char>());

Nie wiem skąd bierzesz składnię t.open("file.txt", "r"). Z tego, co wiem, to nie jest metoda, która std::ifstream ma. Wygląda na to, że się pomyliłeś. z C fopen.

Edit: zwróć również uwagę na dodatkowe nawiasy wokół pierwszego argumentu do konstruktora łańcuchowego. są niezbędne. Zapobiegają one problemowi znanemu jako " najbardziej irytujący parse", który w tym przypadku nie spowoduje błędu kompilacji, jak zwykle, ale da interesujące (Czytaj: złe) wyniki.

Podążając za punktem Keithba w komentarzach, oto sposób, aby to zrobić, który przydziela całą pamięć z przodu (zamiast w zależności od automatycznej realokacji klasy string):

#include <string>
#include <fstream>
#include <streambuf>

std::ifstream t("file.txt");
std::string str;

t.seekg(0, std::ios::end);   
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);

str.assign((std::istreambuf_iterator<char>(t)),
            std::istreambuf_iterator<char>());
 554
Author: Tyler McHenry,
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-02-23 19:31:27

Jest kilka możliwości. Ten, który lubię, używa stringstream jako pośrednika:

std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();

Teraz zawartość pliku.txt " są dostępne w postaci buffer.str().

Inna możliwość (choć na pewno mi się to nie podoba) jest o wiele bardziej podobna do Twojej oryginalnej:

std::ifstream t("file.txt");
t.seekg(0, std::ios::end);
size_t size = t.tellg();
std::string buffer(size, ' ');
t.seekg(0);
t.read(&buffer[0], size); 

Oficjalnie nie jest to wymagane do pracy w standardzie C++98 lub 03 (string nie jest wymagany do przechowywania danych w sposób ciągły), ale w rzeczywistości działa ze wszystkimi znanymi implementacjami, A C++11 i późniejsze wymagają ciągłego przechowywania, więc gwarantowana jest praca z nimi.

Co do tego, dlaczego nie lubię tego drugiego, jak również: po pierwsze, ponieważ jest dłuższy i trudniejszy do odczytania. Po drugie, ponieważ wymaga to inicjalizacji zawartości łańcucha z danymi, na których Ci nie zależy, a następnie natychmiastowego zapisania tych danych(TAK, Czas inicjalizacji jest zwykle trywialny w porównaniu do odczytu, więc prawdopodobnie nie ma to znaczenia, ale dla mnie nadal wydaje się to trochę złe). Po trzecie, w pliku tekstowym, pozycja X w plik nie musi oznaczać, że będziesz musiał czytać znaki X, aby osiągnąć ten punkt-nie jest wymagane, aby wziąć pod uwagę rzeczy, takie jak tłumaczenia końca linii. Na prawdziwych systemach, które wykonują takie tłumaczenia (np. Windows) przetłumaczona forma jest krótsza niż to, co jest w pliku (np. "\R\n" w pliku staje się "\n" w przetłumaczonym łańcuchu), więc wszystko, co zrobiłeś, jest zarezerwowane trochę dodatkowego miejsca, którego nigdy nie używasz. Ponownie, tak naprawdę nie powoduje większego problemu, ale i tak czuje się trochę źle.

 893
Author: Jerry Coffin,
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
2019-09-18 18:05:22

Myślę, że najlepszym sposobem jest użycie string stream. prosto i szybko !!!

#include <fstream>
#include <iostream>
#include <sstream> //std::stringstream
int main() {
    std::ifstream inFile;
    inFile.open("inFileName"); //open the input file

    std::stringstream strStream;
    strStream << inFile.rdbuf(); //read the file
    std::string str = strStream.str(); //str holds the content of the file

    std::cout << str << "\n"; //you can do anything with the string!!!
}
 74
Author: mili,
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
2019-06-05 12:57:19

Może nie znajdziesz tego w żadnej książce lub stronie, ale dowiedziałem się, że działa całkiem dobrze:

ifstream ifs ("filename.txt");
string s;
getline (ifs, s, (char) ifs.eof());
 14
Author: Ankit Acharya,
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-12-25 12:30:55

Wypróbuj jedną z tych dwóch metod:

string get_file_string(){
    std::ifstream ifs("path_to_file");
    return string((std::istreambuf_iterator<char>(ifs)),
                  (std::istreambuf_iterator<char>()));
}

string get_file_string2(){
    ifstream inFile;
    inFile.open("path_to_file");//open the input file

    stringstream strStream;
    strStream << inFile.rdbuf();//read the file
    return strStream.str();//str holds the content of the file
}
 6
Author: madx,
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-02-05 12:50:38

Wymyśliłem inny sposób, który działa z większością strumieni, w tym std::cin!

std::string readFile()
{
    stringstream str;
    ifstream stream("Hello_World.txt");
    if(stream.is_open())
    {
        while(stream.peek() != EOF)
        {
            str << (char) stream.get();
        }
        stream.close();
        return str.str();
    }
}
 3
Author: yash101,
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
2019-06-05 12:58:41

Jeśli zdarzy ci się użyć glibmm Możesz spróbować Glib::file_get_contents.

#include <iostream>
#include <glibmm.h>

int main() {
    auto filename = "my-file.txt";
    try {
        std::string contents = Glib::file_get_contents(filename);
        std::cout << "File data:\n" << contents << std::endl;
    catch (const Glib::FileError& e) {
        std::cout << "Oops, an error occurred:\n" << e.what() << std::endl;
    }

    return 0;
}
 1
Author: Artem Vorotnikov,
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-07 14:55:31

Mógłbym to zrobić tak:

void readfile(const std::string &filepath,std::string &buffer){
    std::ifstream fin(filepath.c_str());
    getline(fin, buffer, char(-1));
    fin.close();
}

Jeśli jest to coś, na co warto się pochylić, proszę daj mi znać dlaczego

 0
Author: chunkyguy,
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-10-22 12:55:00

Myślę, że nie można tego zrobić bez jawnej lub niejawnej pętli, bez wczytania do tablicy znaków (lub innego kontenera) najpierw i ten konstruując łańcuch. Jeśli nie potrzebujesz innych możliwości ciągu znaków, można to zrobić za pomocą vector<char> w ten sam sposób, w jaki obecnie używasz char *.

 -4
Author: KeithB,
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
2010-04-08 17:30:26