2

我已经在网上浏览了一些东西,SOF 解释了“文件编码”,但我仍然有疑问。文件是一组相关的记录,在磁盘上,它的内容只是存储为'1'和'0'。每次,一个正在运行的程序想要读入一个文件或写入该文件,该文件就会被带入 RAM 并放入正在运行的程序(又名进程)的地址空间中。现在是什么决定了文件中的位(或字节)应该如何解码/编码以及读取和显示/写入?

关于 SOF 有一种解释,它读作“在存储级别,文件包含一个字节数组。除此之外,您还有文本文件的编码层。格式层位于最后,位于文本文件的编码层之上,或位于所有其他二进制文件的字节数组之上。我对此很好,但想知道它是否 100% 正确。

这个问题基本上是在理解 C++ 中的文件打开模式时出现的。

4

5 回答 5

2

让我们看看这是否有帮助......

一个 Unix 文件只是一个位数组 (1/0),文件中当前的最小位数是 8,即 1 个字节。所有文件交互都在不低于字节级别完成。在当今的大多数系统上,您实际上不必担心文件的最大大小。操作系统中仍然存在一些小的差异,但如果没有最大大小小于 1 GB 的系统,则很少有差异。

文件的编码或格式仅取决于使用它的应用程序。

有许多常见的文件格式,例如“unix ASCII 文本”和 PDF。您将遇到的大多数文件都会在网络上的某个地方有文档化的格式规范。例如,“Unix ASCII 文本文件”的规范是:

一组 ascii 字符,其中每行都以行尾字符结尾。行尾字符在 c++ 中指定为 std::endl' 或带引号的“\n”。Unix 将此字符指定为二进制值 - 012(oct) 或 00001010。

希望这可以帮助 :)

于 2013-02-23T15:26:12.420 回答
2

如何编码/显示某些东西的决定完全取决于程序的设计者。当然,某些类型的文件有标准——PDF 或 JPG 文件的内容有标准格式。PDF 和 JPG 的定义都相当复杂。

文本文件至少有一些标准——但是如何解释或使用文本文件的内容可能与 JPEG 一样复杂和令人困惑——唯一的区别是内容是(某种)文本,所以你可以在文本编辑器中加载它并尝试理解它。但请参阅下面的“数据库类型应用程序中的文本”示例行。

在 C 和 C++ 中,基本上只有一个区别,文件是“二进制”或“文本”(“非二进制”)。不同之处在于“特殊位”的处理,主要与“结尾”有关 - 文本文件将包含行尾标记或换行符('\n')[更多关于换行符],并且在某些操作系统中,也包含“文件结束标记” - 例如在旧 CP/M 中,文件大小为 128 或 256 字节的块。所以如果我们有"Hello, World!\n"在文本文件中,该文件的长度为 128 个字节,其余 114 个字节将是“文件结束”标记。大多数现代操作系统以字节为单位跟踪文件大小,因此不需要在文件中包含文件结束标记。但是 C 支持许多新旧操作系统,因此该语言对此有所考虑。文件结尾通常是 CTRL-Z(DOS、Windows 等)或 CTRL-D(Unix - Linux 等)。当 C 运行时库遇到文件结尾字符时,它将停止读取并给出错误代码/行为,就像“这里没有要读取的文件”一样。

行尾或换行需要特殊处理,因为它们在文件所在的操作系统中并不总是相同的。例如,Windows 和 DOS 使用“回车换行”(CR、LF - CTRL-M、CTRL-J、ASCII 13 和 10 分别)作为行尾。在各种形式的 Unix 中(例如 Linux、MacOS X 和 BSD),行尾是单独的“换行符”(LF、CTRL-J)。在较旧的 MacOS 中,行尾仅是“回车”。因此,作为程序员的您不必担心行结束的确切方式,C 运行时库会将“本机”行尾转换为标准化的行尾'\n'(转换为“换行”或字符值 10)。当然,这意味着C运行时库需要知道“如果有一个CR后跟LF,

对于二进制文件,我们真的不希望对数据进行任何转换,仅仅因为我们的像素恰好是彼此相邻的值 13 和 10,并不意味着我们希望将其合并为单个 10 字节,对吗?如果代码读取值 26 (CTRL-Z) 或 4 (CTRL-D) 的字节,我们当然不希望输入停在那里......

现在,如果我有一个包含以下内容的数据库文本文件:

 10 01353-897617 14000 Mats

你可能几乎不知道这意味着什么——我的意思是你可能知道“垫子”是我的名字——但也可能是那些放在眼镜下的小纸板东西(又名“啤酒垫”)或其他东西在地板上,例如为穆斯林准备的“祈祷垫”。

数字 10 可以是客户编号、商品编号、“行号”或类似的东西。01353-896617 几乎可以是任何东西——也许是我的电话号码[不,不是,但确实很像]——但它也可以是“制造商零件号”或某种形式的序列号等。14000?每件商品的价格、库存单位的数量、我的薪水 [我希望不会!]、从我的地址到澳大利亚悉尼的距离(我想大概是)。

我敢肯定,没有其他任何东西的其他人可能会想出数百个其他答案。

[事实是,为了这个答案的目的,它只是胡说八道,除了“电话号码”开头的那位,这是一个有效的英国区号 - 重点是解释“a的含义只有在描述字段含义的内容时才能理解文本文件中的字段集"]

当然,这同样适用于二进制文件,只是由于缺少分隔符,通常更难弄清楚内容是什么——如果上面的文本中没有空格和破折号,那就更难了知道什么属于哪里,对吧?二进制文件中通常没有“空格”和其他类似的东西。这完全取决于某人在某处代码中的描述或定义,或类似的东西。

我希望我在这里的漫谈能给你一些想法。

于 2013-02-23T15:41:04.807 回答
2

我认为这里对层顺序的描述令人困惑。我会认为格式和编码是相关的,但不会紧密联系在一起。让我们尝试正式定义它。

文件是连续的字节序列一个字节是一个连续的位序列。

符号是数据的单位。字节是一种符号。还有其他不是字节的符号。考虑数字 6 - 它是一个符号,但不是一个字节。然而,它可以被编码为一个字节,通常为00000110(这是 6 的二进制补码编码)。

编码将一组符号映射到另一组符号。最常见的是,它从一组非字节符号映射到字节,当应用于整个文件时,它会成为文件编码。二进制补码给出数值的表示。另一方面,例如,ASCII 以字节表示拉丁字母和相关字符。如果你把 ASCII 应用到一个文本字符串上,比如“Hello, World!”,你会得到一个字节序列。如果将此字节序列存储为文件,则文件编码为 ASCII。

格式描述了一组有效的符号序列。当应用于文件的字节时,它是一种文件格式。一个例子是用于存储光栅图形的 BMP 文件格式。它指定开头必须有几个字节来标识文件格式为 BMP,后跟几个字节来描述图像的大小和深度,依此类推。不是文件格式的格式示例是我们如何用英语编写十进制数字。基本格式是一系列数字字符,后跟一个可选的小数点和更多的数字字符。

文本文件

文本文件是一种格式非常简单的文件。它的格式非常简单,因为它没有结构。它立即以字符的某种编码开始,并以最终字符的编码结束。通常没有页眉或页脚或元数据或类似的东西。您只需从头开始将字节解释为字符。

但是你如何解释文件中的字符呢?这就是编码的用武之地。如果文件被编码为 ASCII,则该字节01000001表示拉丁字母 A。还有更复杂的编码,例如 UTF-8。在 UTF-8 中,字符不一定用单个字节表示。有些可以,有些不能。您从第一个字节的前几位确定要解释为字符的字节数。

当您在您最喜欢的文本编辑器中打开文件时,它如何知道如何解释字节?嗯,这是一个有趣的问题。文本编辑器必须确定文件的编码。它可以尝试以多种方式做到这一点。有时文件名通过其扩展名给出提示(.txt可能至少与 ASCII 兼容)。有时文件的第一个字符可以很好地提示编码是什么。但是,大多数文本编辑器都会让您选择指定将文件视为哪种编码。

文本文件可以有格式。通常格式完全独立于文本的编码。也就是说,格式根本没有描述有效的字节序列。相反,它描述了有效的字符序列。例如,HTML 是一种用于标记文档的文本文件格式。它描述了确定文档内容的字符序列(注意:不是字节序列)。例如,它表示字符序列<html>是一个开始标签,并且必须在某个点后跟结束标签</html>。当然,格式比这要详细得多

二进制文件

二进制文件是具有由其文件格式决定的含义的文件。文件格式描述了文件中有效的字节序列以及该序列的含义。在文件格式级别重要的不是对字节的某种解释——而是字节的顺序和排列。

如上所述,BMP 文件格式提供了一种存储光栅图形的方法。它说前两个字节必须是01000010 01001101,接下来的四个字节必须给出文件的大小作为字节数的计数,依此类推,直到实际的像素数据。

二进制文件可以在其中包含编码。为了说明这一点,请考虑前面的示例。我说过 BMP 文件中前两个字节后面的四个字节给出了文件的大小(以字节为单位)。这些字节是如何解释的?BMP 文件格式声明这些字节将大小作为无符号整数给出。这是这些字节的编码。

因此,当您浏览计算机上的目录以查找 BMP 文件并打开它时,您的系统如何知道如何打开它?它如何知道使用哪个程序来查看它?与文本文件的编码相比,文件扩展名更强烈地暗示二进制文件的格式。如果文件名.bmp末尾有,您的系统可能会认为它是一个 BMP 文件,只需在您拥有的任何图形程序中打开它即可。它还可能会查看前几个字节并查看它们的建议。

概括

理解文件中字节含义的第一层次是该文件的格式。文本文件的格式非常简单——从头开始,解释字符直到结束。您如何解释字符取决于该文本文件的字符编码。然而,大多数格式都更复杂,并且可能会在其中嵌套编码。在某种程度上,你必须开始从你的字节中提取抽象信息,这就是编码开始的地方。但是任何被编码的东西也可以有一个应用到它的格式。在获得所需信息之前,您拥有一系列格式和编码。

于 2013-02-23T17:12:19.127 回答
1

所以基本上我们主要讨论的是文本文件,对吧?

现在重点:当您的文本编辑器将文件加载到内存中时,它会根据一些信息推断出其文件编码(您告诉它,或者它在文件的前几个字节中具有特殊的文件格式标记,或其他)。然后是程序本身决定它如何处理原始字节。

例如,如果您告诉文本编辑器以 ASCII 格式打开文件,它会将每个字节视为一个单独的字符,并且A只要遇到数字 65 作为当前要显示的字节,它就会显示该字符,等等(因为 65 是)的 ASCII 字符代码A

但是,如果您告诉它以 UTF-16 格式打开文件,那么它将一次抓取两个字节(更准确地说,是两个八位字节),它将使用这个所谓的“单词”作为数值查找,例如,ç当它读取的两个字节对应于231的 Unicode 字符代码时,它将显示一个字符ç

于 2013-02-23T15:18:43.360 回答
1

现在是什么决定了文件中的位(或字节)应该如何解码/编码以及读取和显示/写入?

文件的格式,很明显。如果您正在读取 BMP 文件,则必须先读取文件头,然后读取height*width像素数据。如果您正在阅读.txt,请按原样阅读字符。文本文件可以有不同的编码,例如 Unicode。

某些格式(例如.png.

具体算法的选择取决于各种因素。在 Windows 上,重要的通常是扩展名。在网络中,content type占主导地位。

一般来说,如果你尝试读取其他格式的文件,你通常会得到垃圾。有时可能会被迫这样做:.bmp例如,尝试在文本编辑器中打开文件。

于 2013-02-23T15:17:31.617 回答