it-swarm.com.de

Lesen Sie die gesamte Datei ASCII in C ++ std :: string

Ich muss eine ganze Datei in den Speicher einlesen und in einem C++ std::string ablegen.

Wenn ich es in einen char[] einlesen würde, wäre die Antwort sehr einfach:

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 ...

Jetzt möchte ich genau dasselbe tun, aber einen std::string anstelle eines char[] verwenden. Ich möchte Schleifen vermeiden, d. H. Ich nicht möchte:

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()

Irgendwelche Ideen?

551
Escualo

Update: Es stellt sich heraus, dass diese Methode, obwohl sie die STL-Redewendungen gut befolgt, tatsächlich überraschend ineffizient ist! Tun Sie dies nicht mit großen Dateien. (Siehe: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html )

Sie können einen streambuf-Iterator aus der Datei erstellen und den String damit initialisieren:

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

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

Ich bin nicht sicher, woher Sie die Syntax t.open("file.txt", "r") beziehen. Soweit ich weiß, ist das keine Methode, die std::ifstream hat. Sie haben es anscheinend mit Cs fopen verwechselt.

Bearbeiten: Beachten Sie auch die zusätzlichen Klammern um das erste Argument für den Zeichenfolgenkonstruktor. Dies sind wesentliche . Sie verhindern das als " ärgerlichste Syntaxanalyse " bekannte Problem, das in diesem Fall nicht wie gewohnt zu einem Kompilierungsfehler führt, sondern interessante (sprich: falsche) Ergebnisse liefert.

In Anlehnung an den Punkt von KeithB in den Kommentaren sehen Sie hier eine Möglichkeit, den gesamten Arbeitsspeicher im Voraus zuzuweisen (anstatt sich auf die automatische Neuzuweisung der Zeichenfolgenklasse zu verlassen):

#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>());
493
Tyler McHenry

Es gibt einige Möglichkeiten. Eine, die ich gerne als Zwischenstation für einen Stringstream nutze:

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

Jetzt ist der Inhalt von "file.txt" in einem String als buffer.str() verfügbar.

Eine andere Möglichkeit (obwohl es mir sicherlich nicht so gut gefällt) ist viel eher wie Ihr Original:

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); 

Offiziell ist dies nicht erforderlich, um unter dem C++ 98- oder 03-Standard zu funktionieren (Zeichenfolge ist nicht erforderlich, um Daten zusammenhängend zu speichern), aber tatsächlich funktioniert es mit allen bekannten Implementierungen, und C++ 11 und höher erfordern zusammenhängenden Speicher Es ist also garantiert, dass es mit ihnen zusammenarbeitet.

Und warum mag ich letzteres auch nicht? Erstens, weil es länger und schwerer zu lesen ist. Zweitens, weil es erforderlich ist, dass Sie den Inhalt der Zeichenfolge mit Daten initialisieren, die Sie nicht interessieren, und diese Daten dann sofort überschreiben (ja, die Zeit für die Initialisierung ist im Vergleich zum Lesen normalerweise trivial, es spielt also wahrscheinlich keine Rolle , aber für mich fühlt es sich immer noch falsch an). Drittens bedeutet Position X in einer Textdatei nicht unbedingt, dass Sie X-Zeichen gelesen haben, um diesen Punkt zu erreichen - es ist nicht erforderlich, Dinge wie Zeilenende-Übersetzungen zu berücksichtigen. Auf realen Systemen, die solche Übersetzungen ausführen (z. B. Windows), ist das übersetzte Formular kürzer als der Inhalt der Datei (dh "\ r\n" in der Datei wird zu "\ n" in der übersetzten Zeichenfolge) ist ein wenig mehr Platz reserviert, den Sie nie nutzen. Auch dies ist kein großes Problem, fühlt sich aber trotzdem ein wenig falsch an.

743
Jerry Coffin

Ich denke, der beste Weg ist, String-Stream zu verwenden. einfach und schnell !!!

#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!!!
}
62
mili

Sie können dies in keinem Buch oder auf keiner Website finden, aber ich habe herausgefunden, dass es ziemlich gut funktioniert:

ifstream ifs ("filename.txt");
string s;
getline (ifs, s, (char) ifs.eof());
11
Ankit Acharya

Versuchen Sie eine dieser beiden Methoden:

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
madx

Ich habe einen anderen Weg gefunden, der mit den meisten Istreams funktioniert, einschließlich 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();
    }
}
2
yash101

Wenn Sie glibmm verwenden, können Sie Glib :: file_get_contents versuchen.

#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

Ich könnte es so machen:

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

Wenn dies etwas ist, über das man die Stirn runzeln kann, lass es mich bitte wissen, warum

0
chunkyguy