Datei komplett in String einlesen
-
Kóyaánasqatsi schrieb:
std::ifstream::good() checkt nur die Zugriffsrechte, bzw. ob die Datei noch gelesen oder bearbeitet werden kann. Was du suchst ist sehr wahrscheinlich std::ifstream::eof().
Das stimmt nicht.
good()
berücksichtigteof()
. Bei Erreichen des Dateiendes wird vongood()
entsprechendfalse
zurückgegeben.
-
> std::ifstream::good() checkt nur die Zugriffsrechte, bzw. ob die Datei noch gelesen oder bearbeitet werden kann.
Wie kommst du auf diese Idee? good() prüft, ob der Filestate das ios_base::goodbit ist. Sobald das ios_base::eofbit gesetzt ist, wird good() automatisch false zurückgeben.
> Außerdem solltest du tmp_array keine feste Elemente-Zahl geben, da das undynamisch ist.
Nicht nur das, es ist auch noch gefährlich, damit ist ein Bufferoverflow vorprogrammiert.
std::fstream fs("datei.txt", std::ios_base::binary); if(!fs) { std::cerr << "could not open file\n"; std::abort(); } std::vector<std::string> tmp_vec; std::string temp; while(fs >> temp) // ---> operator >>() gibt streamreferenz zurück --> ausführung von operator !() tmp_vec.push_back(temp);
-
Danke euch allen
Ebenfalls solltest du über den Namensraum std auf die Funktionen zugreifen, um Zugriffsverletzungen und lästige Kompilierfehler zu vermeiden.
Das verstehe ich nicht
Warum vermeide ich mit std Zugriffsverletzungen und Compilerfehler?
-
Wenn du die Datei einfach nur einlesen willst, gibts einen viel zuverlässigeren(und vermutlich auch schnelleren) Weg:
#include <iterator> #include <fstream> #include <string> std::string get_file_as_string(const char* filename) { std::fstream file(filename, std::ios_base::out); file << std::noskipws; if(file.bad()) throw std::runtime_error("error when opening file \'" + std::string(filename) + "\'"); std::istream_iterator begin(file), end_of_file; return std::string(begin, end_of_file); } #include <iostream> int main() { std::string text = get_file_as_string("./test.txt"); std::cout << text << std::endl; }
bb
-
Du vermeidest Namensraumkonflikte. In Implemtierungsdateien (.cpp) kannst Du aber eigentlich machen was du willst. In öffentlichen Headern solltest Du aber ein öffentliches using namespace xyz vermeiden.
-
Okey, habs verstanden
-
unskilled schrieb:
Wenn du die Datei einfach nur einlesen willst, gibts einen viel zuverlässigeren(und vermutlich auch schnelleren) Weg:
#include <iterator> #include <fstream> #include <string> std::string get_file_as_string(const char* filename) { std::fstream file(filename, std::ios_base::out); file << std::noskipws; if(file.bad()) throw std::runtime_error("error when opening file \'" + std::string(filename) + "\'"); std::istream_iterator begin(file), end_of_file; return std::string(begin, end_of_file); } #include <iostream> int main() { std::string text = get_file_as_string("./test.txt"); std::cout << text << std::endl; }
bb
Wenn schon, dann
std::istream_iterator<char> begin(file), end_of_file;
-
Vermutlich die einfachste Lösung:
std::ifstream in(filename); std::ostringstream s; s << in.rdbuf(); // std::ostream& operator<<(std::ostream&, std::streambuf*) liest den kompletten Inhalt std::string myData = s.str();
-
@Ad aCTa: erwischt
^^
@tntnet: naja... ich würds so nciht machen : P
kürzer ist es nur, weil ich ne extra fkt gebaut hab und das nicht öffnen abfange(wieso auch immer, aber es kann ja ganz hilfreich sein, zu wissen, dass die datei nicht geöffnet wurde und nciht einfach nur leer ist)2. wird dort imho auch im release hin- und her-kopiert...
da strings idR als vector (am stück-speicher) implementiert sind, heißt das also, dass du bei großen dateien 2x ganz viel speicher am stück brauchst - die wahrscheinlichkeit ist also wesentlich höher, dass bad_alloc fliegt...bb
-
unskilled schrieb:
@Ad aCTa: erwischt
^^
@tntnet: naja... ich würds so nciht machen : P
kürzer ist es nur, weil ich ne extra fkt gebaut hab und das nicht öffnen abfange(wieso auch immer, aber es kann ja ganz hilfreich sein, zu wissen, dass die datei nicht geöffnet wurde und nciht einfach nur leer ist)2. wird dort imho auch im release hin- und her-kopiert...
da strings idR als vector (am stück-speicher) implementiert sind, heißt das also, dass du bei großen dateien 2x ganz viel speicher am stück brauchst - die wahrscheinlichkeit ist also wesentlich höher, dass bad_alloc fliegt...bb
Klar kann ich nach dem anlegen des ifstreams abfragen, ob es geklappt hat. Fehlerprüfung habe ich der einfachheit halber mal weg gelassen.
Zu deinem 2. Punkt: Dein Code ist mindestens genauso ineffizient. Der istream_iterator ist kein random access iterator. Daher kann der string-Konstruktor nicht feststellen, wie viele Zeichen kommen. Er kann nur Zeichenweise vom Iterator lesen und in seinen Puffer übernehmen. Da muss er beim alloziieren raten, wie viele Zeichen noch kommen.
Bei meiner Methode kann der istream operator für streambuf wenigstens abfragen, wie viele Zeichen momentan im Puffer stehen und so die Zeichen blockweise lesen. Das kann performanter sein. Da gibt es ein wenig mehr Optimierungspotential für den Implementierer der Standardbibliothek.
Will man wirklich vermeiden, dass die Daten hin und her kopiert werden, muss man beispielsweise mit stat vorher die Dateigrösse abfragen und dann mit std::string::reserve den Speicher vorreservieren.
Im übrigen solltest Du Dir mal den streambuf_iterator anschauen. Der wäre für Deinen Fall ein wenig besser geeignet. Da entfällt dieses noskipws.