User:Arnie97/Off Topic
跳到导航
跳到搜索
数据对象的内部表示(变量)
数据在内存中以不同的方式(数据结构)储存着。这些数据结构当中有顺序的(例如线性表的数组形式),也有非顺序的(例如线性表的链表形式)。
数据对象的外部表示(文件)
为了将数据,尤其是非顺序的数据:
- 保存于外存(硬盘、光盘、闪存等)的某个文件中以备后用
- 通过网络等方式共享给另一台计算机
- 通过串口等方式传送至图形计算器等设备
我们需要将数据编码为字符串(字节流)方能储存或传输,这一编码过程称为序列化(Serialization)。
变量的类型系统:静态类型与动态类型
变量是代指数据的名称、符号。
- 在 C++、Java 等语言中,每个变量均对应一个特定的数据类型,使用前必须声明每个变量的数据类型,这样的类型系统称为静态类型。
- 在 Haskell 等语言中,虽然很多情况下不需手动声明变量的数据类型,而是通过计算机的自动推导来确定数据类型,但每个变量均有特定的类型——类似 C++ 11 中使用
auto
的情形——因此同样属于静态类型。 - 在 Python、JavaScript 等语言中,类型依附于变量中储存的数据本身,数据有类型而变量无类型,这样的类型系统称为动态类型。
文件的类型判定:扩展名与特征签名
类比变量,文件名(和路径)是代指文件的符号。对于文件来说,同样有数种不同的方式来记录它的类型,其中就包括:
- 文件名称的某个特定部分指示一个文件的类型——通常是最后一个小数点后的部分,也就是扩展名(Extension)。
- 文件内容的某个特定部分,即特征签名(File Signature)指示一个文件的类型——通常是最前面的部分,也就是头部(Header)。
扩展名最早在 CP/M 操作系统中被采用,而后又随一脉相承的 DOS 和 Windows 得到了推广;特征签名则在 Unix 中被广泛应用,而后又被 Linux 等操作系统所继承下来。由于两类操作系统均得到了广泛的应用,现实中两种方式常常共存:
文件类型 | 扩展名 | 特征签名[1] |
---|---|---|
PDF 文档 | %PDF
| |
ZIP 压缩文件 | zip docx pptx xlsx 等 | PK (设计者 Phil Katz)
|
RAR 压缩文件 | rar | Rar!
|
CAB 压缩文件 | cab | MSCF (Microsoft Cabinet File)
|
MZ 可执行文件 | com exe
exe dll sys ocx cpl scr 等 |
MZ (设计者 Mark Zbikowski)
(为向下兼容 DOS,PE 文件头部与之相同) |
ELF 可执行文件 | 无 | \x7F E L F
|
PNG 图片 | png | \x89 P N G
|
GIF 图片 | gif | GIF89a 或 GIF87a
|
JPEG 图片 | jpg jpeg | 以 \xFF \xD8 开始,\xFF \xD9 结束
|
Midi 音轨 | midi | MThd (MIDI Track header)
|
Java 字节码 | class | \xCA \xFE \xBA \xBE ,即十六进制 CAFEBABE
|
从上面的例子中可以看出,既有一个扩展名对应多种特征签名的情况(如 GIF 文件),也有多种扩展名对应单一特征签名的情况(如 PE 文件)。当扩展名和特征签名共存时,有时会结合两种因素来决定文件如何解析,更多时候则只选择其中的主要因素来判断文件的类型。例如,将 JPEG 图片的扩展名更改为 png 仍能用多数图片查看器正常打开,说明这些软件仅通过文件内容中的特征签名来判断文件的格式,扩展名无关紧要。