3

我一直在阅读有关此主题的信息,但没有得到我的问题的具体信息:

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

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

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

这 255 个代码分为以下2几组:

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

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

1) 正确吗?

2)现在,假设我将一个 INT 保存在二进制文件中。(32 位系统中 4 个字节)

该文件如何告诉程序读取它:它不是4 个不相关的单个字节,而是一个is4 个字节的 int?

4

3 回答 3

3

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

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

好吧,它不知道——它只是按照它所说的去做。

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

如果您正在编写自己的程序,如果您想将所有内容存储为二进制文件,则可以使用编写BinaryWriter和读取使用。BinaryReader如果你写 usingBinaryWriter和读 using会发生什么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);
}

你会得到胡言乱语(如果它有效的话)。然而,文件中没有任何内容可以预先告诉您。那里没有特别的信息。程序必须根据一些带外信息(某种规范)知道要做什么。

于 2012-04-29T07:07:58.583 回答
2

所以二进制文件包含整个范围的字符代码:0..255(ascii 字符+特殊字符)。

不,二进制文件只包含字节。介于 0 和 255 之间的值。如果您决定将其含义赋予它们,则它们应该只被视为字符。如果它是二进制文件(例如 JPEG),那么您不应该这样做 - 图像数据中的字节 65 在逻辑上不是“A” - 它是文件中该点处的字节 65 的任何含义。

(请注意,即使是文本文件也不会分为“ASCII 字符”和“特殊字符”——这取决于编码。在 UTF-16 中,每个代码单元占用两个字节,无论其值如何。在 UTF-8 中, bytes 取决于您要表示的字符。)

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

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

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

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

Im Cmd shell....你已经编写了你的​​二进制文件。我不知道你在那里做了什么。我怎么知道是一次读取 4 个单字节还是 4 个字节?

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

如果它确实需要知道数据的含义,那么仅仅知道它是一个四字节整数并没有太大帮助——它需要知道该整数意味着什么才能对它做任何有用的事情。所以你的文件是从命令外壳写的......这是什么意思?如果我不知道这意味着什么,我知道一次读取一个字节还是将四个字节作为整数读取有什么关系?

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

于 2012-04-29T07:20:29.447 回答
1

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

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

  • 一个字符串 ( Hello Soohjun)
  • 12 个单字节字符的序列(H, e, l, l, o, , S, o, o, h, j, u, n
  • 由 3 个无符号整数组成的序列,后跟一个字符(1214606444、1864389487、1869113973、110)
  • 一个字符后跟一个浮点数,然后是一个无符号整数,然后是一个浮点数(72、6.977992E22、542338927、4.4287998E24),依此类推...

是选择这些字节含义的人,另一个程序会对相同的数据做出不同的解释,就像字母组合在英语和法语中具有不同的解释一样。

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

于 2012-04-29T07:29:20.137 回答