写入二进制文件并用各种程序打开后,为啥结果不符合预期?

Posted

技术标签:

【中文标题】写入二进制文件并用各种程序打开后,为啥结果不符合预期?【英文标题】:After writing to a binary file and opening it with various programs, why are the results not as expected?写入二进制文件并用各种程序打开后,为什么结果不符合预期? 【发布时间】:2013-07-23 22:09:23 【问题描述】:

基本上我正在尝试写入二进制文件,以便在使用文本编辑器打开它时会显示所有 ASCII 字符。我注意到这适用于记事本,但不适用于记事本++或开放式办公室并给出奇怪的结果。为什么?

#include <fstream>
using namespace std;
int main () 
    ofstream file ("file.bin", ios::binary);
    for(int num = 0; num < 128; num++)
        file.write (reinterpret_cast<const char *>(&num), sizeof(num));
    file.close ();
    return 0;

所以我希望文件在使用文本编辑器打开时大致重现this ASCII chart。当我用记事本打开它时,我得到了这个

   !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /   0 

1 2 3 4 5 6 7 8 9 : ; ? @A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x yz | ~

当我用记事本++打开它时,我得到了这个

当我使用 OpenOffice.org Writer 打开它时,我选择默认选项以使用“西欧(Windows 1252/WinLatin 1)”打开并得到一堆###。这是否与字节顺序标记有关?

我尝试修改程序以使用file.write (reinterpret_cast&lt;const char *&gt;(&amp;num), sizeof(char));,因为int 被强制转换为char,但随后程序崩溃。

出于好奇,有人解释了为什么 OpenOffice 编写者会提出# 和空格?

【问题讨论】:

你得到了所有的 ASCII,每一个都由三个空字符分隔。那是你的意图吗?当你说它不起作用时,这是什么意思?你看到了什么“奇怪的结果”?记事本++会崩溃吗?会显示中文吗? @MooingDuck 三个空字符从何而来?我更新了问题。 检查您的屏幕截图,Notepad++ 显示正确的输出 @MooingDuck 你是怎么得出这个结论的? 10 是 'A' 的 ASCII,我没有看到任何 'A'。 如果你仔细观察,你可以看到输出是 little-endian 的。酷。 【参考方案1】:
for(int num = 0; num < 128; num++)
    file.write (reinterpret_cast<const char *>(&num), sizeof(num));

在这些行中,您将数字num 以二进制形式写入一个 4 字节整数。 (sizeof(num),其中numint)。由于您写入的所有值都小于 128,因此num 的前三个字节始终为0x000000。因此,对于您编写的每个值,您将获得三个空值,然后是您想要的 ASCII 字符。

Microsoft 记事本绝对是愚蠢的,当它遇到不可打印的 ASCII 字符时,例如 NULL,它只会显示一个空格。注意你的 ASCII 值之间是如何有“空格”的。另外,我敢打赌它看起来更像这样,我用下划线替换了一些空格。请注意,第 10 个值(新行)会导致新行。

_________
__            !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?   @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _   `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z      |      ~   

Notepad++ 更加智能,它不会将所有奇怪的东西转换为空格,而是显示它们的名称或编号。 Notepad++ 本身似乎也对字符 13(回车)感到困惑,因为 13 通常也是新行的一部分。它(合理地)决定也将其设为一条新线。 Notepad++ 对这个文件的处理可以说是更正确的。这可以通过查看前八个字符来验证:“NUL NUL NUL NUL - SOH NUL NUL NUL”首先是零,然后是“SOH”字符。如果我们查看您的 ASCII 图表,它会显示第一个 ASCII 字符是“SOH - 标题开头”。

【讨论】:

以上是关于写入二进制文件并用各种程序打开后,为啥结果不符合预期?的主要内容,如果未能解决你的问题,请参考以下文章

为啥python使用eval函数输出结果有很多尾数

为啥很多项目不提供预编译的二进制文件?

程序打开同一个命名管道并用 C 多次写入

如何将MATLAB运行结果写入txt文件

c# 将字符串以二进制形式写入文件

python处理完CSV数据后重新写入新CSV文件,为啥新文件用记事本打开没有双引号?该怎么解决?谢谢