文本文件与二进制文件

所有人都知道,计算机的世界里只有二进制的 0 和 1。一切都是用二进制来存储的。那为什么还有文本文件和二进制文件之分呢?

要回答这个问题,先要知道位、字节和字的概念: 是的,计算机的世界里只有 0 和 1。存储一个 0 或者 1 的内容/空间大小称为一个 binary digit(bit,汉语称为位、比特)。8 个 binary digit 等于 1 byte(字节)。而 1 word(字) = 2 , 4 or more bytes。word 是 CPU 类型的标志,平时说的 32 位、64 位电脑就是说 CPU 的一个字是 32 个 binary digit,还是 64 个 binary digit。

存储人类理解的字符,不管是一个英文字母还是一个汉字,都需要用特定方式转为二进制的 0 和 1。这种特定的方式就是『编码方案』,比如一个怎样的 0 和 1 的序列表示大写字母 A,就由编码方案规定。显然,在制定这个方案时,我们首先需要确定多少个 bit 表示一个人类理解的字符。对于这个问题,就有了两种做法:固定长度的编码方案和不定长度的编码方案。固定长度的编码方案,比如最早,目前最广泛的 ASCII 码,是把 8 个 bit 对应一个拉丁字母,这也是为什么一个字节是 8 个 bit 的原因。而不定长度编码是说多少个 bit 代表一个字符是不定的,这非常利于减小文件的大小。比如,用文件存放人的身份信息,一个人一个文件,那么可以指定一个特定的编码方案。比如文件的头 160 个 bit 和 ASCII 的规定相同,这样表示人的名字(假设人的名字只可能在 20 个人类理解的字符以内),接下来一个 bit 区分性别,而不是再用 8 个bit,等等。我们把用固定程度的编码方案的文件,称为文本文件,在这样的文件中,记录每一个人类理解的字符都占用固定长度的 bit。我们把用不定长度的编码方案的文件,称为二进制文件,在这样的文件中,记录一个人类理解的字符所占用的 bit 长度是不定的。

不同的字符编码

一个字节只有 8 个 bit,所以 ASCII 码只能包含 2 的八次方种字符,也就是 256 种。这对于英语这样的语言,已经足够了,但是中文这样的语言就不够。于是,有了 UNICODE 编码(可以翻译为万国码)。最常用的 UNICODE 标准是用两个字节表示一个字符,这样就能支持 256 * 256 种字符。然而,如果文本基本上是英文的话,UNICODE 码比 ASCII 码多需一倍的存储空间。所以,本着节约的精神,又出现了 UTF-8 编码。UTF-8 编码把一个字符根据不同的数字大小编码成 1-6 个字节,常用的英文字母被编码成 1 个字节,汉字通常是 3 个字节,很生僻的字符会被编码成 4-6 个字节,UTF-8 编码有一个额外的好处,就是 ASCII 编码可以看成是 UTF-8 编码的子集,所以,大量只支持 ASCII 码的历史遗留软件可以在 UTF-8 编码下继续工作。在计算机内存中,统一使用 UNICODE。保存和传输时,就转换为 UTF-8。

因为法律的原因,中文版 Windows 系统的记事本在保存时默认不是使用的 UTF-8,而是国标码:GB-18232 或者 GB-18030(GB 读作国标)。所以 Windows 上保存的文本文件放到 Linux 上中文是乱码。解决这个问题的命令是:

iconv -f gb2312 -t utf-8 doc.txt
  • 输入/输出格式规范:

    • -f, –from-code=名称 原始文本编码
    • -t, –to-code=名称 输出编码
  • 信息:

    • -l, –list 列举所有已知的字符集

    • 输出控制:

    • -c 从输出中忽略无效的字符

    • -o, –output=FILE 输出文件

    • -s, –silent 关闭警告

    • –verbose 打印进度信息

不同的换行方式

这是计算机时代来临之前的工具遗留下来的产物。机械打字机在打完一行后,需要回到该行的开头,然后移动到下一行。回到该行的开头,这叫做『回车(return)』。移动到下一行,叫做『换行(newline)』。之后有了电子打字机、电传打字机(电传打字机类似于今天的传真)等等。这些设备因为各种原因继承了『回车』和『换行』。

到了计算机时代,讲道理来说,在完成一行的文字后,依然必定需要一个机制记录一行的结束。UNIX 操作系统在行尾使用『换行』表示结尾。Linux 操作系统继承了这一点。Mac 电脑早年是用的『回车』表示结尾,现在改为『换行』了。Windows 操作系统则和早年的打字机保持一致使用『回车』+『换行』的方式。需要指出的是,很多人把『回车』和『换行』直接写为『\r』和『\n』。这种写法是采用的 C 语言等编程语言的方式,很多编程语言用这种转义符的形式来表示。在说明文件换行方式这个问题时,这样写只是让读者理解而已。文件中既不会真的在人理解的层面写有『\r』和『\n』,更不可能在二进制的层面写一个反斜杠和字母。实际使用的是编码方案特定的方式,不同的编码方案中『换行』和『回车』和一般字符一样有一个对应的编码。采用相同编码方案保存文件,不同的操作系统的做法的不同仅仅在于是否使用『换行』或者『回车』。因为 Linux 和 Mac 只使用『换行』,所以 Linux 和 Mac 保存的文件在 Windows 看来换行不完整,人看到的就是没有换行。反过来,Linux 和 Mac 会认为 Windows 的文件每一行正确换行了,然后还有一个特殊字符 ^M (不是 ^ 和 M 的组合),所以人会看到换行正确。这里说的 Linux、Mac 和 Windows 操作系统的做法,是指这些操作系统的标准做法,比如这里说 Windows 的做法指的是 Windows 的默认编辑器——记事本的做法。如果你在 Windows 使用专业的编辑器,依然可以handle这个问题。在 Linux,一些专业的编辑器也会对 ^M 这样的特殊字符特殊显示出来。

Windows 文件转为 Linux 文件:

  1. sed 命令
sed -e 's/^M//g' original.txt > target.txt (注意^M 在Linux/Unix下是这样输入的:先按CTRL+v,接着按CTRL+SHIFT+m)
sed -e 's/.$//' dos.txt > linux.txt
  1. 在vi中替换
:%s/^M//g

Linux 文件转为 Windows 文件:

sed -e 's/$/\r/' linux.txt > dos.txt

参考链接

http://www.cnblogs.com/zhangjiankun/archive/2011/11/27/2265184.html

http://www.cnblogs.com/zmlctt/p/3710302.html