二进制输出应该与 ASCII 输入相同吗?
Should the binary output be the same as the ASCII input?
我正在编写一个读取 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
任何帮助将不胜感激。
谢谢。
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);
}
现在输出文件的内容将与输入文件的内容相同。某些系统可能会进行换行符转换,可能会因为输入文件是以文本模式打开而导致内容不同。
以文本模式或二进制模式打开文件与ASCII/binary转换无关。
这与操作系统如何处理一些特殊字符(例如换行符)、行大小限制或文件扩展名有关。
在 fopen Linux 手册页中:
The mode string can also include the letter 'b' either as a last character or as a character between the characters in any of the two-character strings de‐
scribed above. This is strictly for compatibility with C89 and has no effect; the 'b' is ignored on all POSIX conforming systems, including Linux. (Other
systems may treat text files and binary files differently, and adding the 'b' may be a good idea if you do I/O to a binary file and expect that your program
may be ported to non-UNIX environments.)
有关以文本或二进制模式打开文件的详细信息,请参阅
现在,回到 ASCII 转换:
计算机中的所有数据都存储在位中,所以最终一切都是二进制的。
包含 ASCII 字符的文本文件也是二进制文件,只是其内容可以以有意义的方式映射到 ASCII table 字符。
看看 ASCII table。 ASCII 字符编号零 (0
) 的二进制值为 0x30
。这意味着您在文本文件中看到的零实际上是
内存中的二进制数0x30
。
您的程序正在从一个文件读取数据并写入另一个文件,但未执行任何 ASCII/binary 转换。
另外,这里有个小错误:
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,任何十六进制编辑器程序都可以完成这项工作。
我正在编写一个读取 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
任何帮助将不胜感激。
谢谢。
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);
}
现在输出文件的内容将与输入文件的内容相同。某些系统可能会进行换行符转换,可能会因为输入文件是以文本模式打开而导致内容不同。
以文本模式或二进制模式打开文件与ASCII/binary转换无关。 这与操作系统如何处理一些特殊字符(例如换行符)、行大小限制或文件扩展名有关。
在 fopen Linux 手册页中:
The mode string can also include the letter 'b' either as a last character or as a character between the characters in any of the two-character strings de‐ scribed above. This is strictly for compatibility with C89 and has no effect; the 'b' is ignored on all POSIX conforming systems, including Linux. (Other systems may treat text files and binary files differently, and adding the 'b' may be a good idea if you do I/O to a binary file and expect that your program may be ported to non-UNIX environments.)
有关以文本或二进制模式打开文件的详细信息,请参阅
现在,回到 ASCII 转换:
计算机中的所有数据都存储在位中,所以最终一切都是二进制的。
包含 ASCII 字符的文本文件也是二进制文件,只是其内容可以以有意义的方式映射到 ASCII table 字符。
看看 ASCII table。 ASCII 字符编号零 (0
) 的二进制值为 0x30
。这意味着您在文本文件中看到的零实际上是
内存中的二进制数0x30
。
您的程序正在从一个文件读取数据并写入另一个文件,但未执行任何 ASCII/binary 转换。
另外,这里有个小错误:
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,任何十六进制编辑器程序都可以完成这项工作。