我正在编写一个程序,它读取一个ASCII文件,然后将它转换成一个二进制文件,正如我所看到的,这并不是一个很难的任务,但是了解背后发生的事情是.
据我所知,ASCII文件只是人类可读的文本,所以如果我们想要创建一个充满ASCII文件的新文件,一个简单的带有fputc()的循环就足够了,对于一个二进制文件fwrite()来说,这就足够了吗?
因此,我的问题是,一旦完成了从ASCII到二进制的转换,我应该在我的.bin文件中看到什么?它应该用完全相同的符号<88><88><88><88><88>填充。
代码:
/*
* From "Practical C Programming 2nd Edition"
* Exercise 14-4: Write a program that reads an ASCII file containing a list of numbers
* and writes a binary file containing the same list. Write a program that goes the
* other way so that you can check your work.
*
*/
#include <stdio.h>
#include <stdlib.h>
const char *in_filename = "bigfile.txt";
const char *out_filename = "out_file.bin";
int main()
{
int ch = 0;
/* ASCII */
FILE *in_file = NULL;
in_file = fopen(in_filename, "r");
if(!in_file)
{
fprintf(stderr, "ERROR: Could not open file %s ... ", in_filename);
exit(EXIT_FAILURE);
}
/* Binary */
FILE *out_file = NULL;
out_file = fopen(out_filename, "w+b");
if(!out_file)
{
fprintf(stderr, "ERROR: New file %s, could not be created ... ", out_filename);
exit(EXIT_FAILURE);
}
while(1)
{
ch = fgetc(in_file);
if(ch == EOF)
break;
else
fwrite(in_file, sizeof(char), 1, out_file);
}
fclose(in_file);
fclose(out_file);
return 0;
}我用这个shell脚本生成输入文件:
tr -dc "0-9" < /dev/urandom | fold -w100|head -n 100000 > bigfile.txt任何帮助都是非常感谢的。
谢谢。
发布于 2021-06-26 03:39:54
以文本模式或二进制模式打开文件与ASCII/二进制转换无关。这与操作系统如何处理某些特殊字符(如新行字符)、行大小限制或文件扩展名有关。
在fopen Linux手册页中:
模式字符串还可以将字母'b‘作为最后一个字符,也可以作为上述任何两个字符字符串中任意一个字符之间的字符。这完全是为了与C89兼容,没有任何效果;在所有符合POSIX的系统(包括Linux )上,'b‘都被忽略。(其他系统可能以不同的方式对待文本文件和二进制文件,如果在二进制文件中执行I/O操作,并期望将程序移植到非UNIX环境,则添加'b‘可能是个好主意。)
有关以文本或二进制模式打开文件的详细信息,请参阅https://stackoverflow.com/a/20863975/6874310。
现在,回到ASCII转换:
计算机中的所有数据都是以位的形式存储的,所以最终一切都是二进制的。
包含ASCII字符的文本文件也是二进制文件,但其内容可以以有意义的方式映射到ASCII表字符。
看一看ASCII表。ASCII字符号零(0)的二进制值为0x30。这意味着您在文本文件中看到的零实际上是内存中的二进制数字0x30。
您的程序正在读取文件中的数据,并将数据写入另一个文件,而不执行任何ASCII/二进制转换。
此外,这里有一个小错误:
fwrite(in_file, sizeof(char), 1, out_file);可能应该是:
fwrite(&ch, sizeof(char), 1, out_file);这将变量ch中的字节写入out_file。使用此修复,程序基本上从文件bigfile.txt中读取数据,并将完全相同的数据写入文件out_file.bin,而不进行任何转换。
若要将单个数字ASCII数字转换为二进制数字,请以字节(char类型)从输入文件中读取该数字,并从中减去0x30:
char ch = fgetc(in_file);
if(ch == EOF)
{
break;
}
else if (isdigit(ch))
{
ch = ch - 0x30;
fwrite(&ch, sizeof(char), 1, out_file);
}现在,您的输出文件实际上是二进制文件。使用isdigit确保字节是ASCII号。在文件的开头添加#include <ctype.h>以使用它。
因此,对于具有以下文本的小输入文件:
123它的二进制表示将是:
0x313233在将ASCII数字转换为二进制后,二进制内容将是:
0x010203要将其转换回ASCII,只需反向转换即可。也就是说,将0x30添加到二进制文件的每个字节。
如果使用类似Unix的系统,可以使用命令行工具(如xxd )检查二进制文件。在Windows上,任何十六进制编辑器程序都将完成这项工作。
发布于 2021-06-25 23:59:41
fwrite(in_file, sizeof(char), 1, out_file);是错误的,因为给定一个整数时指针是预期的。
您可以使用fputc编写一个字节,如
fputc(in_file, out_file);如果出于某些原因仍然希望使用fwrite,请准备一个数据来编写和编写如下所示
{
unsigned char in_file_byte = in_file;
fwrite(&in_file_byte, sizeof(in_file_byte), 1, out_file);
}现在,输出文件的内容将与输入文件相同。有些系统可能会执行换行符的转换,因为输入文件是以文本模式打开的,因此可能会使内容不同。
https://stackoverflow.com/questions/68138098
复制相似问题