manejo - ¿Cómo leer el contenido de un archivo en una cadena en C?
leer cadena de caracteres en c (8)
Otra solución, lamentablemente muy dependiente del sistema operativo, es la asignación de memoria del 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.
El código 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, por otro lado, es un poco más complicado, y desafortunadamente no tengo un compilador delante de mí para probar, pero la funcionalidad es proporcionada por CreateFileMapping()
y MapViewOfFile()
.
¿Cuál es la forma más simple (menos propensa a errores, menos líneas de código, como quiera interpretarla) para abrir un archivo en C y leer su contenido en una cadena (char *, char [], lo que sea)?
Si "lee su contenido en una cadena" significa que el archivo no contiene caracteres con el código 0, también puede usar la función getdelim (), que acepta un bloque de memoria y lo reasigna si es necesario, o simplemente asigna el búfer completo para usted, y lee el archivo en él hasta que encuentra un delimitador o un final de archivo especificado. 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 muestra puede verse 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 */
Si el archivo es texto y desea obtener el texto línea por línea, la manera 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 stdin o un tubo, no podrá usar 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''. La mejor manera de leer un archivo es usar read 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;
}
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);
}
}
Tiendo a simplemente cargar todo el búfer como un fragmento 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 apéndice que uso 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...
}
Recién modificado de la respuesta aceptada arriba.
#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);
}
// 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 cruda porque nada se compara con nulo.