Como ler o conteúdo de um arquivo em uma string em C?

Qual é a maneira mais simples (menos propenso a erros, menos linhas de código, porém você quer interpretá-lo) para abrir um arquivo em C e ler seu conteúdo em uma string (char *, char [], o que for)?

Eu costumo carregar apenas o buffer inteiro como um pedaço de memory bruta na memory e fazer a análise por conta própria. Dessa forma, eu tenho o melhor controle sobre o que a biblioteca padrão faz em várias plataformas.

Este é um esboço que eu uso para isso. Você também pode querer verificar os códigos de erro para fseek, ftell e fread. (omitido para maior clareza).

 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... } 

Outra solução, infelizmente altamente dependente do sistema operacional, é a memory mapeando o arquivo. Os benefícios geralmente incluem o desempenho da leitura e o uso reduzido de memory, pois a exibição de aplicativos e o cache de arquivos dos sistemas operacionais podem, na verdade, compartilhar a memory física.

O código POSIX ficaria assim:

 int fd = open("filename", O_RDONLY); int len = lseek(fd, 0, SEEK_END); void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0); 

O Windows, por outro lado, é um pouco mais complicado e, infelizmente, eu não tenho um compilador na minha frente para testar, mas a funcionalidade é fornecida por CreateFileMapping() e MapViewOfFile() .

Se “ler seu conteúdo em uma string” significa que o arquivo não contém caracteres com o código 0, você também pode usar a function getdelim (), que aceita um bloco de memory e o realoca, se necessário, ou apenas aloca todo o buffer para você e lê o arquivo nele até encontrar um delimitador ou fim de arquivo especificado. Apenas passe ‘\ 0’ como o delimitador para ler o arquivo inteiro.

Esta function está disponível na Biblioteca GNU C, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994

O código de amostra pode parecer tão simples quanto

 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 */ 

Se o arquivo é texto e você deseja obter o texto linha por linha, a maneira mais fácil é usar fgets ().

 char buffer[100]; FILE *fp = fopen("filename", "r"); // do not use "rb" while (fgets(buffer, sizeof(buffer), fp)) { ... do something } fclose(fp); 

Se você estiver lendo arquivos especiais como stdin ou pipe, você não poderá usar o fstat para obter o tamanho do arquivo antecipadamente. Além disso, se você estiver lendo um arquivo binário, fgets perderá as informações de tamanho da string devido aos caracteres ‘\ 0’ incorporados. A melhor maneira de ler um arquivo é usar read e realloc:

 #include  #include  #include  #include  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; } 

Se você estiver usando o glib , use 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); } } 
 // 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 é uma solução bem crua, porque nada é verificado em relação a null.

Apenas modificado da resposta aceita acima.

 #include  #include  #include  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); }