fwrite продолжает давать сбой, не уверен почему

#c #fwrite

#c #fwrite

Вопрос:

В моем коде ниже файл записывается правильно, насколько я могу судить. Когда я смотрю в файл, всплывает.dat Я вижу этот поток двоичных ÍÌL@33c@ÍÌÜ@ffFAßOeA^@^@bBf6zE33äCff<83>BÍ̦B

Однако моя программа всегда заканчивает запуском этого оператора if:

 if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
{
   fprintf(stderr, "Problem reading some or all data from %snn", binaryFileName);
   return EXIT_FAILURE;
}
  

Кто-нибудь видит, что я что-то здесь сделал не так? Полный код ниже.

 #include <stdlib.h>
#include <stdio.h>
#define LENGTH 10

int main(void)
{
   FILE *binaryFile, *textFile;
   char *binaryFileName = "floats.dat", *textFileName = "floats.txt";
   float floats[LENGTH] = {3.2, 3.55, 6.9, 12.4, 14.332, 56.5, 4003.4, 456.4, 65.7, 83.4};
   float inputFloats[LENGTH];
   int i;

   if((binaryFile = fopen(binaryFileName, "r ")) == NULL)
   {
      fprintf(stderr, "Problem opening %s", binaryFileName);
   }

   if(fwrite(floats, sizeof(float), LENGTH, binaryFile) < LENGTH)
   {
      fprintf(stderr, "Problem writing some or all data to %sn", binaryFileName);
      return EXIT_FAILURE;
   }

   printf("DATA WRITTEN SUCCESSFULLYn");

   if(fread(inputFloats, sizeof(float), LENGTH, binaryFile) < LENGTH)
   {
      fprintf(stderr, "Problem reading some or all data from %snn", binaryFileName);
      return EXIT_FAILURE;
   }

   for(i = 0; i < LENGTH; i  )
   {
      printf("float[%d] = %fn", i, floats[i]);
   }

   return EXIT_SUCCESS;
}
  

Комментарии:

1. Существуют ли отдельные позиции файла для чтения и записи в один и тот же файл? Если нет, fread пытается прочитать значения с плавающей запятой за теми, которые вы только что написали. В этом случае используйте rewind(binaryFile) .

Ответ №1:

  • Вы не работаете с текстовыми данными, поэтому вам следует указать двоичный режим при открытии файла. Используйте r b вместо r
  • Вам нужно fseek(binaryFile, 0, SEEK_SET) «перемотать» файл после записи. rewind также может быть использовано для этого случая — fseek позволяет вам размещать указатель чтения / записи там, где вы хотите.

Комментарии:

1. Это идеально, спасибо, Эрик. Есть ли какие-либо недостатки в использовании более простого вызова, такого как то, что @steabert использовал ниже — rewind (двоичный файл)?

2. Кроме того, я просто играл, и теперь, когда это работает, я все еще получаю тот же результат, даже при использовании ‘r ‘. Является ли указание ‘r b’ отказоустойчивым для вашего кода в случае, если он перенесен на другую систему, возможно, с другой реализацией fopen, которая не допускает использование двоичных файлов при открытии с помощью ‘r ‘?

3. @Chris Paynter: rewind здесь все в порядке. Однако вы должны знать об fseek . r b гарантирует, что никто не работает со встроенным n — это может быть не нужно на вашей платформе

Ответ №2:

FILE Структура хранит запись о том, на какую часть файла она в данный момент указывает. Поскольку вы только что выполнили запись в binaryFile , указатель на файл находится в конце того, что вы написали.

Поэтому вам необходимо перемотать файл назад, используя fseek(binaryFile, 0, SEEK_SET); перед чтением.

Ответ №3:

Вы забыли перемотать файл перед его чтением:

 rewind(binaryFile);
  

Ответ №4:

Когда вы заканчиваете запись в файл, указатель на ФАЙЛ находится в его конце, поэтому, конечно, если вы попытаетесь прочитать, это не сработает. Попробуйте использовать fseek для перемещения указателя в начало файла перед чтением.

Пожалуйста, избегайте этого :

 if((binaryFile = fopen(binaryFileName, "r ")) == NULL) {
  

и предпочитаю это:

 binaryFile = fopen(binaryFileName, "rb ");
if(!binaryFile) {
  

Комментарии:

1. Нет ничего плохого в присваивании в состоянии, когда оно так же четко читаемо, как здесь.

2. = при условном переходе это того не стоит. Лучше перестраховаться, чем потом сожалеть.