使用 fread 从 .txt 文件中读取 unsigned char 会给出不同的值

Posted

技术标签:

【中文标题】使用 fread 从 .txt 文件中读取 unsigned char 会给出不同的值【英文标题】:Reading unsigned char from .txt file using fread give different values 【发布时间】:2015-05-28 05:55:39 【问题描述】:

我截取了以下代码以从 .txt 文件中读取 16 个无符号字符值。

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

int main()


 int i, j, k, load_size;
 unsigned char *buf;
 load_size = 16;
 buf = (unsigned char *)malloc(load_size);
 FILE *fin;
 fin = fopen("demo_input1.txt", "r");
 fread(buf, 1, load_size, fin);
 for(i=0;i<16;i++)
    printf("%d ", *buf);                         
    buf++;
 
 system("PAUSE");



文件“demo_input1.txt”包含值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16。但我在控制台值中得到输出 49 32 50 32 51 32 52 32 53 32 54 32 55 32 56 32。任何人都可以告诉我这里出了什么问题来帮助我吗?谢谢

【问题讨论】:

你需要 fscanf 而不是 fread。 49 = 0x31 这是'1'的ASCII码点值 【参考方案1】:

fread 用于读取原始输入。由于您的文件是格式化文本,请使用以下内容:

int nums[SIZE];
int count = 0;
while( fscanf(fin, "%d", nums + count) == 1 ) 
  if(++count == SIZE) break; /* More than expected numbers in file */

稍后您可以使用以下方式打印:

for(i = 0; i < count; i++) 
    printf("%d ", nums[i]);                         

fscanf 是从文件中读取格式化输入的一种方式。您可以使用mallocwalking pointers,如原始代码 sn-p 所示或根据您的要求。

【讨论】:

'fscanf(buf, "%d", nums + count)' 不应该是 'fscanf(fin, "%d", nums + count)' 吗?因为,fin 是这里的流。 @amin__ 抱歉,打错了。已更新。 没关系。那么,在格式化文本的情况下,没有可行的文件 io 来一次读取所有数据而不是使用循环?【参考方案2】:

发生的事情完全正确,但不是您所期望的。发生什么了?您从文件中读取 1 个字节到 char,然后使用 %d 输出它,它将以十进制输出。看一个ascii表,如果你读到char1,它的ASCII值是4932是空格,502,以此类推。您不能只读取这样的纯数字,您的代码将%d 替换为%c 仅适用于二进制文件,而不适用于人类可读的文件。

您想使用 fscanf 代替 fread,它的工作方式类似于 scanf,但从文件中读取。在那里您可以指定读取一个整数,从而获得没有空格的整数。这些您可以检查它们是否小于256,如果是,则转换为char。

【讨论】:

那么,有没有办法用 fread 做到这一点?我需要使用 fscanf 循环吗? @amin__ 如果您想阅读整行,那么您可以采用我的方法.. fread() 可用于读取预定义的字节数,然后对该缓冲区执行操作,如图所示在我的回答中 当然,如果你愿意,你可以用 fread 来做这件事,但是之后它会变得非常复杂。如前所述, fread 读取原始数据。如果您以二进制模式存储文件,这将很有用。你当然可以使用 fread 读入一个数组,直到你到达文件末尾或一个空格,然后将数组数据转换为unsigned char,但这很不切实际。【参考方案3】:

另一种方法是使用fgets() 将整行读取到缓冲区中,使用空格作为分隔符将行换行,然后将字符串转换为整数并存储或打印它们。

char buf[300];
int a[30],i=0;
while(fgets(buf,sizeof(buf),fin))

   char *p = strtok(buf," ");
   i = 0;
   while( p != NULL)
   
      a[i] = atoi(p);
      printf("%d ",a[i]);
      i++;
      p = strtok(NULL," ");
   

PS:当使用fgets() 时,您需要有预定义的大数组来保存您的输入,否则可能会导致错误的结果。

【讨论】:

此代码可以生成错误值。例如。这是你的内容:10 11 12 13 14 15 16,我们假设缓冲区更小并且被填满:10 11 12 13 1,那么你将把14 减半,得到14 值。 @Nidhoegger 您需要保持缓冲区足够大以容纳整个输入。否则没有fgets() 您可以在使用fgets 之后查看文件结尾或空格是否是下一个字符。如果不是,则忽略最后一个值并将文件光标向后移动一点。【参考方案4】:

将空格的ascii值视为32(空格的ASCII)。

只需在 for 循环中进行一项简单的更改。 而不是 %d 使用 %c

for(i=0;i<16;i++)

  printf("%c ", *buf);                         
  buf++;

【讨论】:

以上是关于使用 fread 从 .txt 文件中读取 unsigned char 会给出不同的值的主要内容,如果未能解决你的问题,请参考以下文章

fread 不读取多行

fread函数的用法

Matlab 中fread的问题

matlab 打开bin文件 并转换成为txt文件,送上所有积分

PHP读取文件内容的方法

matlab中使用fwrite将1到10写入文本文件中,再用fread读取该文本文件中的数据,怎么写程序