Разница между спецификациями fread и fgets? - PullRequest
2 голосов
/ 21 апреля 2019

В чем разница между fread и fgets при чтении из файла?Я использую то же выражение fwrite, однако, когда я использую fgets для чтения в файле .txt, он работает как положено, но когда я использую fread (), это не так.

Я переключился с fgets / fputs на fread / fwrite при чтении из файла и в файл.Я использовал fopen (rb / wb) для чтения в двоичных, а не стандартных символах.Я понимаю, что fread получит / 0 нулевых байтов, а не только отдельные строки.

  //while (fgets(buff,1023,fpinput) != NULL) //read in from file
  while (fread(buff, 1, 1023, fpinput) != 0) // read from file

Я ожидаю прочитать из файла в буфер, поместить буфер в общую память, а затем получить ещеобработать чтение из общей памяти и записать в новый файл.

Когда я использую функцию fgets (), она работает как положено с файлами .txt, но при использовании fread добавляет в буфер одну строку из 300 символов в новую строку.Не могу понять, почему.

1 Ответ

1 голос
/ 21 апреля 2019

fgets остановится при встрече с новой строкой.fread нет.Поэтому fgets обычно используется только для текстовых файлов, а fread может использоваться как для текстовых, так и для двоичных файлов.

Из стандарта C11:

7.21.7.2.Функция fgets

Функция fgets считывает самое большее на один символ меньше числа символов, указанного в n, из потока, на который указывает поток, в массив, на который указывает s.Никакие дополнительные символы не читаются после символа новой строки (который сохраняется) или после конца файла.Нулевой символ записывается сразу после последнего прочитанного в массив символа.

7.21.8.1 Функция fread

Функция fread считывает в массив, на который указывает ptr, до nmemb элементов, размер которых равенопределяется размером от потока, на который указывает поток.Для каждого объекта выполняются вызовы размера для функции fgetc, а результаты сохраняются в порядке чтения в массиве беззнаковых символов, точно перекрывающих объект.Индикатор положения файла для потока (если он определен) увеличивается на количество успешно прочитанных символов.Если возникает ошибка, результирующее значение индикатора положения файла для потока является неопределенным.Если частичный элемент читается, его значение является неопределенным.

Этот фрагмент, возможно, прояснит вам ситуацию.Он просто копирует файл кусками.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    if(argc != 3) {
        printf("Usage: ./a.out src dst\n");
        printf("Copies file src to dst\n");
        exit(EXIT_SUCCESS);
    }

    const size_t chunk_size = 1024;

    FILE *in, *out;
    if(! (in = fopen(argv[1], "rb"))) exit(EXIT_FAILURE);
    if(! (out = fopen(argv[2], "wb"))) exit(EXIT_FAILURE);

    char * buffer;
    if(! (buffer = malloc(chunk_size))) exit(EXIT_FAILURE);

    size_t bytes_read;

    do {
        // fread returns the number of successfully read elements
        bytes_read = fread(buffer, 1, chunk_size, in);

        /* Insert any modifications you may */
        /* want to do here                  */

        // write bytes_read bytes from buffer to output file
        if(fwrite(buffer, 1, bytes_read, out) != bytes_read) exit(EXIT_FAILURE);
   // When we read less than chunk_size we are either done or an error has 
   // occured. This error is not handled in this program. 
    } while(bytes_read == chunk_size); 


    free(buffer);
    fclose(out);
    fclose(in);
}

Вы упомянули в комментарии ниже, что хотите использовать это для байтовой передачи.Ну, вы можете просто использовать следующий фрагмент.Просто вставьте его там, где указано в коде выше.

for(int i=0; i < bytes_read - bytes_read%2; i+=2) {
    char tmp = buffer[i];
    buffer[i] = buffer[i+1];
    buffer[i+1] = tmp;
}
...