9 ответов:
Я, как правило, просто загружаю весь буфер как необработанный кусок памяти в память и делаю разбор самостоятельно. Таким образом, у меня есть лучший контроль над тем, что стандартный lib делает на нескольких платформах.
это заглушка, которую я использую для этого. вы также можете проверить коды ошибок для fseek, ftell и fread. (опустим для ясности).
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... }
другое, к сожалению, сильно зависящее от ОС, решение-это сопоставление памяти с файлом. Преимущества, как правило, включают производительность чтения и снижение использования памяти, поскольку представление приложений и кэш файлов операционных систем могут фактически совместно использовать физическую память.
код POSIX будет выглядеть так:
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, с другой стороны, немного сложнее, и, к сожалению, у меня нет компилятора передо мной, чтобы проверить, но функциональность обеспечивается
CreateFileMapping()иMapViewOfFile().
если "читать его содержимое в строку" означает, что файл не содержит символов с кодом 0, вы также можете использовать функцию getdelim (), которая либо принимает блок памяти и перераспределяет его при необходимости, либо просто выделяет весь буфер для вас и читает файл в него, пока он не встретит указанный разделитель или конец файла. Просто передать '\0' в качестве разделителя, чтобы прочитать весь файл.
эта функция доступна в библиотеке GNU C, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
пример кода может выглядеть так просто, как
char* buffer = NULL; size_t len; ssize_t bytes_read = getdelim( &buffer, &len, '', fp); if ( bytes_read != -1) { /* Success, now the entire file is in the buffer */
Если файл является текстовым, и вы хотите получить текст строка за строкой, самый простой способ-использовать fgets().
char buffer[100]; FILE *fp = fopen("filename", "r"); // do not use "rb" while (fgets(buffer, sizeof(buffer), fp)) { ... do something } fclose(fp);
если Вы читаете специальные файлы, такие как stdin или канал, вы не сможете использовать fstat для получения размера файла заранее. Кроме того, если Вы читаете двоичный файл, fgets потеряет информацию о размере строки из-за встроенных символов "\0". Лучший способ прочитать файл - использовать read и 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] = ''; } printf("%.*s\n", len, str); return 0; }
Если вы используете
glib, тогда вы можете использовать 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; }Это довольно грубое решение, потому что ничто не проверяется против null.
просто изменен из принятого ответа выше.
#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] = ''; fread(buffer, 1, length, f); fclose(f); return buffer; } int main() { char *content = readFile("../hello.txt"); printf("%s", content); }
Если вы хотите решение на основе стека:
FILE* f = fopen(file, "r"); if (!f) { fprintf(stderr, "fopen failed\n"); } if (fseek(f, 0, SEEK_END)) { fprintf(stderr, "fseek failed\n"); } const long len = ftell(f); if (len < 0) { fprintf(stderr, "ftell failed\n"); } if (fseek(f, 0, SEEK_SET)) { fprintf(stderr, "fseek failed\n"); } char buf[len + 1]; if (fread(buf, sizeof(char), len, f) != len) { fprintf(stderr, "fread failed\n"); } buf[len] = ''; if (fclose(f)) { fprintf(stderr, "fclose failed\n"); }
Comments