Ascii系列关于二进制文件?

时间:2012-04-29 07:05:07

标签: c# .net-4.0 ascii binary-data

我一直在阅读有关此主题的内容,并没有获得我的问题的具体信息:

(也许以下是不正确的 - 但请纠正我)

每个文件(文本/二进制)都在保存 BYTES

字节为8位,因此最大值为2^8-1 = 255代码。

这255个代码分为2个组:

0..127 : textual chars
128:..255 : special chars.

所以二进制文件包含整个范围的char代码:0..255(ascii chars + special chars)。

1)正确吗?

2)否则,让我说在二进制文件中保存一个INT。 (32位系统中的4字节)

该文件如何告诉progem读取它: 4个单个不相关的字节但是一个is 4个字节的int?

3 个答案:

答案 0 :(得分:3)

所有文件的基础都存储为字节,所以从某种意义上说,你说的是正确的。但是,如果您打开一个打算作为二进制文件读取的文件并尝试在文本编辑器中读取它,它将看起来像乱码。

程序如何知道是以文本还是以二进制形式读取文件? (即作为特殊的ASCII或其他编码字节集,或者作为具有不同表示的底层字节)?

嗯,它不知道 - 只是按照它说的做了。

在Windows中,您在记事本中打开.txt个文件 - 记事本希望阅读文本。尝试在记事本中打开二进制文件。它会打开,你会看到东西,但它会是垃圾。

如果您正在编写自己的程序,则可以使用BinaryWriter进行编写,如果要将所有内容存储为二进制文件,请使用BinaryReader进行阅读。如果您使用BinaryWriter撰写并使用StringReader阅读,会发生什么?


回答你的具体例子:

using (var test = new BinaryWriter(new FileStream(@"c:\test.bin", FileMode.Create)))
{
    test.Write(10);
    test.Write("hello world");
}

using (var test = new BinaryReader(new FileStream(@"c:\test.bin", FileMode.Open)))
{
    var out1 = test.ReadInt32();
    var out2 = test.ReadString();

    Console.WriteLine("{0} {1}", out1, out2);
}

看看你如何阅读所写的相同顺序?该文件没有告诉你任何事情。

现在切换第二部分:

using (var test = new BinaryReader(new FileStream(@"c:\test.bin", FileMode.Open)))
{
    var out1 = test.ReadString();
    var out2 = test.ReadInt32();

    Console.WriteLine("{0} {1}", out1, out2);
}

你会得到喋喋不休(如果它可以工作)。然而,在文件中没有任何东西可以事先告诉你。那里没有特别的信息。该程序必须根据一些带外信息(某种规格)知道该做什么。

答案 1 :(得分:2)

  

所以二进制文件包含整个范围的char代码:0..255(ascii chars + special chars)。

不,二进制文件只包含字节。 0到255之间的值。如果您决定将这些含义归于它们,则它们应仅被视为字符。如果它是二进制文件(例如JPEG),那么你不应该这样做 - 图像数据中的字节65在逻辑上不是'A' - 它是文件中该点的65字节意味着什么。

(请注意,即使文本文件也不分为“ASCII字符”和“特殊字符” - 它取决于编码。在UTF-16中,每个代码单元都占用两个字节而不管其值。在UTF-8中字节数取决于您尝试表示的字符。)

  

该文件如何告诉progem读取它:它不是4个单独的无关字节,而是一个4字节的int?

该文件不告诉程序。程序必须知道如何读取文件。如果您要求记事本打开JPEG文件,它将不会显示图像 - 它会显示乱码。同样,如果您尝试强制图像查看器打开文本文件,就像它是JPEG一样,它会抱怨它已经坏了。

阅读数据的程序需要了解他们将要阅读的数据结构 - 他们必须知道会发生什么。在某些情况下,格式非常灵活,比如XML:有明确指定的层,但程序会读取具有更高层含义的值 - 元素,属性等。在其他情况下,格式绝对精确:首先你' ll以4字节整数开始,然后是两个2字节整数或其他。这取决于格式。

编辑:回答您的具体(重复)评论:

  

Im Cmd shell ....你写了你的二进制文件。我不知道你在那里做了什么。我怎么想知道是否只读取4个单字节或4个字节?

读取数据的程序需要知道数据的含义,否则不知道。如果它只是将文件从一个地方复制到另一个地方,则不需要知道数据的含义。无论是一次复制一个字节还是一次复制所有四个字节都无关紧要。

如果它 需要知道数据的含义,那么只知道它是一个四字节整数并没有多大帮助 - 它需要知道那个整数是什么意思做任何有用的事情。所以你的文件是从命令shell写的......这是什么意思?如果我不知道它意味着什么,我知道一次读一个字节还是整个读四个字节有什么关系呢?

(正如我上面提到的,有一个中间选项,代码可以理解没有意义的结构,并将该结构暴露给其他代码然后强加意义 - XML就是一个典型的例子。)

答案 2 :(得分:1)

这都是解释的问题。文件和系统都不知道文件中发生了什么,他们只是将您的存储视为字节序列,它本身没有任何意义。当你读到一个单词时,你的大脑也会发生同样的事情(你试图选择一种语言来解释它,使字符序列具有意义)。

您的程序有责任以您希望的方式解释数据,因为没有单一的有效解释。例如,字节序列48 65 6C 6C 6F 20 53 6F 6F 68 6A 75 6E可以解释为:

  • 字符串(Hello Soohjun
  • 12个单字节字符的序列(Hello,{{ 1}},Soohju
  • 3个无符号整数后跟一个字符的序列(1214606444,1864389487,1869113973,110)
  • 一个字符后跟一个浮点数,后跟一个unsigned int后跟一个浮点数(72,6.977992E22,542338927,4.4287998E24),等等......

是选择那些字节含义的那个,另一个程序会对同一个数据做出不同的解释,很多相同的字母组合有不同的解释,比如英语和法语。

PS:顺便说一句,这就是逆向工程文件格式的目标:找到每个字节的含义