tabla - Lea el archivo ASCII completo en C++ std:: string
imprimir codigo ascii en dev c++ (9)
Esta pregunta ya tiene una respuesta aquí:
Necesito leer un archivo completo en la memoria y colocarlo en un C ++ std::string
.
Si tuviera que leerlo en un char[]
, la respuesta sería muy simple:
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 ...
Ahora, quiero hacer exactamente lo mismo, pero usando un std::string
lugar de un char[]
. Quiero evitar los bucles, es decir , no quiero:
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()
¿Algunas ideas?
Creo que la mejor manera es utilizar la secuencia de cadena. Sencillo y rápido !!!
ifstream inFile;
inFile.open(inFileName);//open the input file
stringstream strStream;
strStream << inFile.rdbuf();//read the file
string str = strStream.str();//str holds the content of the file
cout << str << endl;//you can do anything with the string!!!
Descubrí otra forma que funciona con la mayoría de los istreams, ¡incluyendo 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();
}
}
Es posible que no encuentres esto en ningún libro o sitio, pero descubrí que funciona bastante bien:
ifstream ifs ("filename.txt");
string s;
getline (ifs, s, (char) ifs.eof());
Hay un par de posibilidades. Una que me gusta usar un stringstream como intermediario:
std::ifstream t("file.txt");
std::stringstream buffer;
buffer << t.rdbuf();
Ahora el contenido de "file.txt" está disponible en una cadena como buffer.str()
.
Otra posibilidad (aunque a mi tampoco me gusta) es mucho más parecida a tu 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);
Oficialmente, no se requiere que esto funcione bajo el estándar C ++ 98 o 03 (no se requiere que la cadena almacene datos de manera contigua) pero en realidad funciona con todas las implementaciones conocidas, y C ++ 11 y posteriores sí requieren almacenamiento contiguo , por lo que está garantizado para trabajar con ellos.
En cuanto a por qué no me gusta lo último también: primero, porque es más largo y más difícil de leer. Segundo, porque requiere que inicialice el contenido de la cadena con datos que no le interesan, y luego los escribe inmediatamente (sí, el tiempo de inicialización suele ser trivial en comparación con la lectura, por lo que probablemente no importa) , pero para mí todavía se siente un poco mal). En tercer lugar, en un archivo de texto, la posición X en el archivo no significa necesariamente que haya leído X caracteres para llegar a ese punto, no es necesario tener en cuenta cosas como las traducciones de fin de línea. En los sistemas reales que realizan dichas traducciones (por ejemplo, Windows), la forma traducida es más corta que lo que hay en el archivo (es decir, "/ r / n" en el archivo se convierte en "/ n" en la cadena traducida), por lo que todo lo que ha hecho Se reserva un poco de espacio extra que nunca utilizas. Una vez más, realmente no causa un problema importante, pero se siente un poco mal de todos modos.
No creo que puedas hacer esto sin un bucle explícito o implícito, sin leer primero una matriz de caracteres (o algún otro contenedor) y diez construyendo la cadena. Si no necesita las otras capacidades de una cadena, se podría hacer con vector<char>
la misma manera que actualmente está usando un char *
.
Pruebe uno de estos dos métodos:
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
}
Si usas glibmm puedes probar 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;
}
Yo podría hacerlo así:
void readfile(const std::string &filepath,std::string &buffer){
std::ifstream fin(filepath.c_str());
getline(fin, buffer, char(-1));
fin.close();
}
Si esto es algo contra lo que fruncirse, por favor, hágamelo saber por qué.
Actualización: ¡ Resulta que este método, aunque sigue bien los modismos STL, es en realidad sorprendentemente ineficiente! No hagas esto con archivos grandes. (Consulte: http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html )
Puedes hacer un iterador de streambuf fuera del archivo e inicializar la cadena con él:
#include <string>
#include <fstream>
#include <streambuf>
std::ifstream t("file.txt");
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
No estoy seguro de dónde está obteniendo la t.open("file.txt", "r")
. Que yo sepa, ese no es un método que std::ifstream
tiene. Parece que lo has confundido con el fopen
de C.
Editar: también tenga en cuenta los paréntesis adicionales alrededor del primer argumento del constructor de cadenas. Estos son esenciales . Evitan el problema conocido como "el análisis más desconcertante ", que en este caso en realidad no le dará un error de compilación como suele hacerlo, pero le dará resultados interesantes (leídos: incorrectos).
Siguiendo el punto de KeithB en los comentarios, aquí hay una manera de hacerlo que asigna toda la memoria por adelantado (en lugar de confiar en la reasignación automática de la clase de cadena):
#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>());