¿Cuál es la forma más simple (menos propensa a errores, menos líneas de código, como quiera interpretarlo) para abrir un archivo en C y leer su contenido en una cadena (char * , char [], lo que sea)La manera más fácil de obtener contenido de archivos en C
Respuesta
Tiendo a simplemente cargar todo el búfer como un trozo de memoria en bruto en la memoria y hacer el análisis por mi cuenta. De esta forma, tengo el mejor control sobre lo que hace la lib estándar en múltiples plataformas.
Este es un stub que utilizo para esto. es posible que también desee verificar los códigos de error para fseek, ftell y fread. (omitido para mayor claridad).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data/extract strings here...
}
Impresionante, que funcionó como un amuleto (y es bastante simple de seguir). ¡Gracias! –
También verificaría el valor de retorno de fread, ya que podría no leer todo el archivo debido a errores y otras cosas. – freespace
En la línea de lo que Freespace dijo, es posible que desee comprobar para asegurarse de que el archivo no es enorme. Supongamos, por ejemplo, que alguien decide alimentar un archivo de 6GB en ese programa ... – rmeador
Si "leer su contenido en una cadena" significa que el archivo no contiene caracteres con código 0, también se puede utilizar getdelim() función, que, o bien acepta un bloque de memoria y reasigna si es necesario, o simplemente asigna todo el buffer para usted, y lee el archivo en él hasta que encuentra un delimitador o un final de archivo especificados. Simplemente pase '\ 0' como el delimitador para leer todo el archivo.
Esta función está disponible en la biblioteca GNU C, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
El código de ejemplo podría ser tan simple como
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim(&buffer, &len, '\0', fp);
if (bytes_read != -1) {
/* Success, now the entire file is in the buffer */
¡Lo he usado antes! Funciona muy bien, suponiendo que el archivo que estás leyendo es texto (no contiene \ 0). – ephemient
NICE! Guarda muchos problemas al sorber en archivos de texto completo. ¡Ahora si hubiera una manera ultra simple similar de leer una secuencia de archivos binarios hasta EOF sin necesitar ningún carácter de delimitación! – anthony
Otro, por desgracia altamente dependiente del sistema operativo, la solución es la cartografía de la memoria en el archivo. Los beneficios generalmente incluyen el rendimiento de la lectura y el uso reducido de la memoria, ya que la vista de aplicaciones y la memoria caché de los sistemas operativos pueden compartir la memoria física.
código de POSIX se vería así:
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
Windows en el otro lado es poco más difícil, y por desgracia no tengo un compilador frente a mí para probar, pero la funcionalidad es proporcionada por CreateFileMapping()
y MapViewOfFile()
.
¡No olvide verificar los valores devueltos de esas llamadas al sistema! –
Si el archivo es texto y desea obtener el texto línea por línea, la forma más fácil es usar fgets().
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
Si está leyendo archivos especiales como entrada estándar o una tubería, que no van a ser capaces de utilizar fstat para obtener el tamaño del archivo de antemano. Además, si estás leyendo un archivo binario, fgets va a perder la información del tamaño de cadena debido a los caracteres incrustados '\ 0'. Mejor manera de leer un archivo, entonces, para su utilización Lea y realloc:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main() {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
Esto es O (n^2), donde n es la longitud de su archivo. Todas las soluciones con más votos ascendentes que esto son O (n). No use esta solución en la práctica, o use una versión modificada con crecimiento multiplicativo. –
realloc() puede ampliar la memoria existente al nuevo tamaño sin copiar la memoria anterior en una nueva pieza de memoria más grande. solo si hay llamadas intermedias a malloc() necesitará mover la memoria y hacer que esta solución sea O (n^2). aquí, no hay llamadas a malloc() que ocurren entre las llamadas a realloc(), por lo que la solución debería estar bien. – Jake
Puede leer directamente en el búfer "str" (con un desplazamiento apropiado), sin necesidad de copiar desde un "buf" intermedio. Sin embargo, esa técnica generalmente sobrecargará la memoria necesaria para el contenido del archivo. También tenga cuidado con los archivos binarios, el printf no los manejará correctamente, ¡y probablemente no quiera imprimir binarios de todos modos! – anthony
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
Esta es una solución bastante crudo porque nada se compara con nula.
Esto solo se aplicará con los archivos basados en disco. Fallará para tuberías con nombre, entrada estándar o flujos de red. – anthony
¡Ha, también por qué vine aquí! Pero creo que es necesario anular el final de la cadena, o devolver la longitud que 'glShaderSource' toma opcionalmente. –
Si está utilizando glib
, puede usar g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Apenas modificado de la respuesta aceptada anteriormente.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
Este no es un código C. La pregunta no está etiquetada como C++. – Gerhardh
@Gerhardh ¡Respuesta tan rápida a la pregunta hace nueve años cuando estoy editando! Aunque la parte de la función es pura C, lamento mi respuesta will-not-run-on-c. – BaiJiFeiLong
Esta antigua pregunta figuraba en la parte superior de las preguntas activas. No lo busqué. – Gerhardh
- 1. ¿La manera más fácil de empaquetar/minificar múltiples archivos javascript?
- 2. La forma más fácil de comparar matrices en C#
- 3. La manera más fácil de crear documentos de contenido dinámico (como facturas, albaranes)
- 4. ¿La manera más fácil de administrar mi CLASSPATH?
- 5. La manera más fácil de reorganizar los métodos en Eclipse
- 6. ¿Cuál es la forma más fácil de obtener una OutOfMemoryException en C#?
- 7. ¿La manera más fácil de comparar dos archivos de Excel en Java?
- 8. ¿La manera más fácil de mostrar la ubicación?
- 9. ¿La manera más fácil de hacer un iterador cíclico (circulador)?
- 10. La forma más fácil de generar archivos de localización
- 11. Comunicación entre aplicaciones C#: la manera fácil
- 12. Cuál es la nube más fácil para contenido web estático
- 13. ¿La forma más fácil de leer datos formateados en C++?
- 14. La manera más fácil de recuperar XmlHttpRequest entre navegadores
- 15. Obtener contenido de archivos en AppHarbor
- 16. La manera más fácil de escribir y leer un XML
- 17. La manera más fácil de convertir "a/b/c" a ["a/b/c", "a/b", "a"]
- 18. ¿La manera más fácil de clasificar los nodos DOM?
- 19. ¿Cuál es la manera más fácil de crear aplicaciones multiproceso con C/C++?
- 20. manera más fácil de programar un sistema de archivos virtual en Windows con Python
- 21. ¿La forma más fácil de firmar/certificar archivos de texto en C++?
- 22. ¿Cuál es la manera más fácil en C# para recortar una nueva línea de una cuerda?
- 23. La manera más fácil de construir/obtener php_memcache.dll para PHP 5.4
- 24. La manera más fácil de probar el código C con Python
- 25. ¿Hay alguna manera fácil de obtener ServerName en Symfony?
- 26. ¡Tiene que haber una manera más fácil de manejar matrices!
- 27. Manera más fácil de mover un proyecto en Eclipse
- 28. manera más fácil de analizar JSON en Qt 4.7
- 29. ¿Manera más fácil de sincronizar 2 hilos en Java?
- 30. ¿Existe alguna manera más fácil de combinar archivos Windows Forms .Designer?
"modo más simple" y "menos propenso a errores" son a menudo opuestos entre sí. –
"forma más simple" y "menos propenso a errores" también son sinónimos en mi libro. Por ejemplo, la respuesta en C# es 'string s = File.ReadAllText (filename);'.¿Cómo podría ser eso más simple y más propenso a errores? –