txt por manejo linea lenguaje leer guardar ejercicios datos crear como binarios archivos archivo c++ text file-io

por - ¿Cuál es la manera más elegante de leer un archivo de texto con c++?



leer archivo txt c++ linea por linea (5)

Me gustaría leer todo el contenido de un archivo de texto en un objeto std::string con c ++.

Con Python, puedo escribir:

text = open("text.txt", "rt").read()

Es muy simple y elegante. Odio las cosas feas, así que me gustaría saber: ¿cuál es la forma más elegante de leer un archivo de texto con C ++? Gracias.


Hay otro hilo sobre este tema.

Mis soluciones de este hilo (ambos de una sola línea):

Lo bueno (ver la segunda solución de Milán):

string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());

y el rápido:

string str(static_cast<stringstream const&>(stringstream() << ifs.rdbuf()).str());


Hay muchas maneras, elige cuál es la más elegante para ti.

Leyendo en char *:

ifstream file ("file.txt", ios::in|ios::binary|ios::ate); if (file.is_open()) { file.seekg(0, ios::end); size = file.tellg(); char *contents = new char [size]; file.seekg (0, ios::beg); file.read (contents, size); file.close(); //... do something with it delete [] contents; }

Into std :: string:

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

En vector <char>:

std::ifstream in("file.txt"); std::vector<char> contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());

En cadena, usando stringstream:

std::ifstream in("file.txt"); std::stringstream buffer; buffer << in.rdbuf(); std::string contents(buffer.str());

file.txt es solo un ejemplo, todo funciona bien para archivos binarios, solo asegúrate de usar ios :: binary en el constructor ifstream.


Me gusta el estilo char * de Milán, pero con std :: string.

#include <iostream> #include <string> #include <fstream> #include <cstdlib> using namespace std; string& getfile(const string& filename, string& buffer) { ifstream in(filename.c_str(), ios_base::binary | ios_base::ate); in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); buffer.resize(in.tellg()); in.seekg(0, ios_base::beg); in.read(&buffer[0], buffer.size()); return buffer; } int main(int argc, char* argv[]) { if (argc != 2) { cerr << "Usage: this_executable file_to_read/n"; return EXIT_FAILURE; } string buffer; cout << getfile(argv[1], buffer).size() << "/n"; }

(con o sin el ios_base :: binary, dependiendo de si desea nuevas líneas traducidas o no. También puede cambiar getfile para simplemente devolver una cadena para que no tenga que pasar una cadena de búfer in. Luego, pruebe para ver si el compilador optimiza la copia al regresar.)

Sin embargo, esto podría verse un poco mejor (y ser mucho más lento):

#include <iostream> #include <string> #include <fstream> #include <cstdlib> using namespace std; string getfile(const string& filename) { ifstream in(filename.c_str(), ios_base::binary); in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>()); } int main(int argc, char* argv[]) { if (argc != 2) { cerr << "Usage: this_executable file_to_read/n"; return EXIT_FAILURE; } cout << getfile(argv[1]).size() << "/n"; }


Pareces hablar de la elegancia como propiedad definitiva del "pequeño código". Esto es, por supuesto, subjetivo en cierta medida. Algunos dirían que omitir todo el manejo de errores no es muy elegante. Algunos dirían que el código claro y compacto que entiendes de inmediato es elegante.

Escriba su propia función / método de una sola línea que lea el contenido del archivo, pero hágalo riguroso y seguro debajo de la superficie y habrá cubierto ambos aspectos de la elegancia.

Todo lo mejor

/ Robert


Pero ten en cuenta que una cadena c ++ (o más concreta: una cadena STL) es tan pequeña como una C-String capaz de contener una cadena de longitud arbitraria, ¡por supuesto que no!

Eche un vistazo al miembro max_size () que le proporciona el número máximo de caracteres que una cadena podría contener. Este es un número de implementación definido y puede no ser portátil entre diferentes plataformas. Visual Studio da un valor de aproximadamente 4gigs para cadenas, otros pueden darte solo 64k y en plataformas de 64 bits, ¡podría darte algo realmente grande! Depende y, por supuesto, normalmente se encontrará con una excepción bad_alloc-exception debido al agotamiento de la memoria mucho antes de alcanzar el límite de 4gig ...

Por cierto: max_size () también es miembro de otros contenedores STL. Le dará el número máximo de elementos de un tipo determinado (para los que ha instanciado el contenedor) que este contenedor (en teoría) podrá contener.

Por lo tanto, si está leyendo desde un archivo de origen desconocido, debe:
- Verifique su tamaño y asegúrese de que sea más pequeño que max_size ()
- Captura y procesa bad_alloc-exceptions

Y otro punto: ¿por qué está interesado en leer el archivo en una cadena? Esperaría procesarlo aún más analizándolo incrementalmente o algo, ¿verdad? Entonces, en lugar de leerlo en una cadena, también podría leerlo en una cadena (que básicamente es solo un poco de azúcar sintáctico para una cadena) y hacer el procesamiento. Pero luego podrías hacer el procesamiento directamente desde el archivo también. Porque si se programa correctamente, la secuencia de cadenas podría ser reemplazada a la perfección por una cadena de archivos, es decir, por el archivo en sí. ¡O también por cualquier otro flujo de entrada, todos comparten los mismos miembros y operadores y por lo tanto pueden intercambiarse sin problemas!

Y para el procesamiento en sí: ¡también hay muchas cosas que puede haber automatizado el compilador! P.ej. digamos que quieres tokenizar la cadena. Al definir una plantilla adecuada, realice las siguientes acciones:
- Lectura de un archivo (o una cadena o cualquier otra secuencia de entrada)
- Tokenizar el contenido
- empujando todos los tokens encontrados en un contenedor STL
- ordenar los tokens alfabéticamente
- Elegir cualquier valor doble
todos (¡) se pueden alcanzar en una sola (!) línea de código C ++ (dejen de lado la plantilla en sí y el manejo de errores)! ¡Es solo una llamada de la función std :: copy ()! Simplemente google para "token iterator" y obtendrás una idea de lo que quiero decir. Entonces, me parece que es aún más "elegante" que solo leer un archivo ...