fread Why возвращает 1 для файла, начинающегося с ff, читаемого в двоичном режиме - PullRequest
1 голос
/ 14 мая 2019

Я пытаюсь прочитать UTF-файл и решил прочитать его в двоичном режиме и пропустить не-ASCII, поскольку файл в основном состоит из корректного английского текста. Я застрял на fread, возвращая 1 вместо числа запрошенных байтов. Первый вывод print_hex IMHO показывает, что он прочитал более 1 символа. Я прочитал несколько примеров чтения двоичных файлов в C, например, Чтение / запись в двоичные файлы в C , прочитал о fread, например. здесь https://en.cppreference.com/w/c/io/fread и здесь Как реально работает fread? , все еще озадаченный, почему он возвращает 1. Файл hexdump, а также полный код на C и вывод ниже.

ADD: скомпилировано gcc, работает в Linux.

Файл:

00000000  ff fe 41 00 41 00 42 00  61 00 0d 00 0a 00 41 00  |..A.A.B.a.....A.|
00000010  41 00 45 00 72 00 0d 00  0a 00 66 00 73 00 61 00  |A.E.r.....f.s.a.|
00000020  6a 00 0d 00 0a 00 64 00  73 00 61 00 66 00 64 00  |j.....d.s.a.f.d.|
00000030  73 00 61 00 66 00 64 00  73 00 61 00 0d 00 0a 00  |s.a.f.d.s.a.....|
00000040  64 00 66 00 73 00 61 00  0d 00 0a 00 66 00 64 00  |d.f.s.a.....f.d.|
00000050  73 00 61 00 66 00 73 00  64 00 61 00 66 00 0d 00  |s.a.f.s.d.a.f...|
00000060  0a 00 0d 00 0a 00 0d 00  0a 00                    |..........|

Код:

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

void print_hex(const char *s)
{
  while(*s)
    printf("%02x ", (unsigned char) *s++);
  printf("\n");
}

int main(){

  #define files_qty 5
  const char* files_array[][2]={{"xx","a"},{"zz","b"},{"xxx","d"},{"d","sd"},{"as","sd"}};

  const char* file_postfix = ".txt";

  char* file_out_name = "XXX_AD.txt";
  FILE* file_out = fopen (file_out_name, "w");

  printf ("This app reads txt files with hardcoded names and writes to file %s\n",file_out_name);

/*  ssize_t bytes_read = 1; //signed size_t */
  size_t n_bytes = 10;
  unsigned char* string_in;
  char* string_out;
  char* file_name;
  string_in = (char*) malloc (n_bytes+1);
  string_out = (char*) malloc (n_bytes+50);
  file_name = (char*) malloc (n_bytes+1); /* more error prone would be to loop through array for max file name length */
  int i;
  size_t n;

  for (i=0;i<files_qty;i++)
  {
    strcpy (file_name,files_array[i][0]);
    FILE* file = fopen (strcat(file_name,file_postfix), "rb");
    if (file!= NULL)
    {
      int k=0;
      while ((n=fread (string_in, sizeof(char), n_bytes, file))>0)
      {
printf("bytes read:%lu\n",(unsigned long) n);
print_hex(string_in);
        int j;
        for (j=0;j<n;j++)
          {
           switch (string_in[j])
             {
               case 0x00:
               case 0xff:
               case 0xfe:
               case 0x0a:
                 break;
               case 0x0d:
                 string_out[k]=0x00;
                 fprintf (file_out, "%s;%s;%s\n", files_array[i][0], files_array[i][1], string_out);
                 k=0;
printf("out:\n");
print_hex(string_out);
                 break;
               default:
                 string_out[k++]=string_in[j]; 
             }

          }
      }
      fclose (file);
     }
     else
     {
      perror (file_name); /* why didn't the file open? */
     }
  }
  free (string_in);
  free (string_out);
  free (file_name);
  return 0;
}

Выход:

bytes read:1
ff fe 41
bytes read:1
0d
out:

bytes read:1
72
bytes read:1
61
bytes read:1
73
bytes read:1
61
bytes read:1
0d
out:
72 61 73 61
bytes read:1
61
bytes read:1
73
bytes read:1
61
bytes read:1
0a

1 Ответ

5 голосов
/ 14 мая 2019

У вас проблема с приоритетом.Простое назначение имеет более низкий приоритет, чем сравнение.Поэтому следующая строка:

while(n=fread (string_in, sizeof(char), n_bytes, file)>0)

оценивается как (дополнительные скобки)

while (n=(fread (string_in, sizeof(char), n_bytes, file)>0))

Поэтому n присваивается как 1, поскольку fread возвращает значение> 0

Вместо этого явно добавьте круглые скобки как:

while((n=fread (string_in, sizeof(char), n_bytes, file))>0)
...