




Я не совсем понимаю, чего вы хотите. Вы хотите постепенно обрабатывать файл, считывая из него одну строку, а затем отказаться от нее и обработать следующую? Или вы хотите прочитать весь файл в буфер? Если вы хотите последнее, я думаю, это уместно (проверьте возврат NULL для malloc и fopen в реальном коде, чтобы узнать, существует ли файл и достаточно ли у вас памяти):
FILE *f = fopen("text.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
fclose(f);
hexdump(bytes); // do some stuff with it
free(bytes); // free allocated memory
Да, это применимо к моему делу. Я имел в виду, что использование realloc после каждого чтения char кажется очень неэффективным, как и после каждого чтения \ n (для расширения массива).
Вы должны открыть файл в двоичном режиме - в противном случае могут возникнуть проблемы (см., Например, руководство по glibc, 12.17)
ой ну спасибо. я понятия не имел, что это делает что большой разницей.
В системах POSIX этого не должно быть. Но я почти уверен, что однажды наткнулся на ошибку, которая исчезла после переключения в двоичный режим, но я не могу вспомнить, в чем именно заключалась проблема ...
Re: двоичный режим - Control-Z может вызвать проблемы в Windows. Общий замечание: вы можете использовать 'stat ()' или 'fstat ()', чтобы сообщить вам размер файла. Также остерегайтесь гигантских файлов (размером более 2 ГБ); долго может не работать надежно.
Функции stat не являются частью стандарта C; fseek () / ftell () - единственный известный мне способ получить размер файла, если вы хотите использовать ISO C.
Я также не знаю другого способа получить размер файла в стандартном C. Но я серьезно сомневаюсь, что он загружает весь файл с 2 ^ 32 байтами в памяти, используя этот метод
привет, в чем разница между (допустим, мы используем 100 вместо pos) char * bytes = malloc (100 * sizeof (char)); и выше строка, в которой вы написали char * bytes = malloc (100); Второй вопрос: а что, если в моем файле 180205962 символа. будет ли вышеупомянутый способ чтения файла эффективным?
@asel, первый вопрос: sizeof(char) определен как 1, поэтому нет никакой разницы. Второй вопрос: нет, вам, вероятно, следует читать его постепенно (например, построчно или каким-либо другим кусочным методом). В противном случае ваша память быстро истощится.
Использование fseek / ftell для получения размера файла небезопасно. См. Этот справочник CERT, чтобы узнать, почему это так и как это сделать безопасно: securecoding.cert.org/confluence/display/seccode/…
@Bryan: Спасибо за ссылку. p.s .: эта страница явно переместилась на securecoding.cert.org/confluence/display/c/…
Если в вашей системе доступен mmap (2), вы можете открыть файл и отобразить его в памяти. Таким образом, у вас не будет памяти для выделения, вам даже не нужно будет читать файл, система сделает это. Вы можете использовать уловку fseek (), которую предоставил litb, чтобы получить размер.
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
РЕДАКТИРОВАТЬ: вы должны использовать lseek(), чтобы получить размер файла,.
int fd = open("filename", O_RDONLY);
int nbytes = lseek(fd, 0, SEEK_END);
void *content = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
@saffsd у вас достаточно репутации, чтобы исправить это, вы знаете, как это работает.
забыл об этом, исправил и удалил комментарий.
Возможно, более идиоматический способ получить размер файла - использовать функцию fstat(2): struct stat S; fstat(fd, &S);, тогда int nbytes = S.st_size - это размер файла в байтах, непосредственно из файловой системы, без каких-либо чтений файла (это, несомненно, даст тот же результат, что и выше; I упомянуть это в основном для полноты).
Если вы хотите использовать ISO C, используйте эта функция.
Это литб-ответ, обернутый некоторой обработкой ошибок ...
Возможно, я неправильно понял, что вы хотите сделать: вы хотите просто прочитать весь файл в большом буфере или вам нужен массив с записью для каждой строки?