美文网首页二进制文件解码编码
Java格式工厂(一)——什么是二进制文件?

Java格式工厂(一)——什么是二进制文件?

作者: 程序员吉森 | 来源:发表于2020-05-19 12:26 被阅读0次

前言

最近在用Java做一个文件格式转化的工具(github地址:https://github.com/lhing17/waterConverter.git),希望通过简单的调用实现一些常用格式间的互相转换,实质上是一些处理不同文件格式的工具包的整合。借此机会,也对Java怎么处理不同格式的文件有了更深入的了解,希望写一系列的文章作为记录。作为开篇,先来聊一聊什么是二进制文件,以及二进制文件到底是怎么存储信息的。

文本文件 vs 二进制文件

我们常说,文件分为文本文件和二进制文件,这其实是一种很糙的分类方式。文件是文本文件还是二进制文件,这是逻辑上的概念,而不是物理上的概念。在物理上,文件都是基于二进制来存储的,文件存储的基本单位是字节,每个字节由8个二进制位组成。如果整个文件能够被某种软件全部解码为字符串,我们就认为这个文件是文本文件。也就是说,文本文件是一种特殊的二进制文件。

同样道理,某种二进制文件如果可以按照位图的方式去解码,它就可以显示为一张图片;如果可以按照
MPEG-3的规则解码,它就可以播放为音频。一些常见的文件格式,都是使用其相应的规范进行编码的。因此,我们可以根据规范编写相应解码的软件,用于读取这些格式的文件。也有一些二进制文件的编码格式是程序开发者自定义的,这样的文件对于普通的用户来说就几乎是保密的。

规范的二进制文件通常都是由多个多字节的序列组成的,每个多字节的序列承载一部分信息。我们以Java的Class文件为例,Class文件是以无符号数和表两种结构来存储信息。

无符号数属于基本数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
表是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。表用于描述有层次关系的复合数据,整个Class文件本质上也可以视作是一张表,这张表由下表所示的数据项按严格顺序排列构成。

表1 Class文件格式

类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count-1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attributes_count 1
attribute_info attributes attributes_count

使用Hexdump类工具查看二进制文件

有的时候,为了开发方便,我们需要去查看二进制文件的结构。前面提到,二进制文件的基本单位是字节,一个字节是由8个二进制位(0或1)组成的。二进制书写和阅读起来都很不方便,为了读写方便,我们通常把二进制转化为16进制。16是2的4次方,因此一个16进制数可以代表4个2进制位。这样,我们就可以用两个16进制数来代表一个字节。有一些工具可以用来查看文件的16进制表示,如Hexdump。Hexdump最初是linux系统上的命令,现在VSCode等工具都提供了hexdump的插件。

图1 VSCode hexdump插件查看文件效果图

image.png

如上图,左侧是二进制文件的16进制表示,右侧是尝试解码为字符的表示。

little-endian vs big-endian

当我们使用多个字节的序列来承载信息时,就出现了字节存储顺序的问题。我们可以把高位字节放在前面,也可以把低位字节放在前面,这就是我们平时说的little-endian和big-endian。

1)Little-endian:将低序字节存储在起始地址(低位编址)
2)Big-endian:将高序字节存储在起始地址(高位编址)

举个例子:
我们有一个整型数据1,它在内存中占据了四个字节的空间,它的16进制表示为:

0x00 00 00 01

在内存中怎么存储呢?
如果你的CPU是intel x86架构的(基本上就是通常我们说的奔腾cpu),那么就是0x01 0x00 0x00 0x00 , 这也就是所谓的little-endian, 低字节存放在内存的低位。如果你的CPU是老式AMD系列的(很老很老的那种,因为最新的AMD系列已经是x86架构了), 它的字节序就是big-endian, 其内存存储就是 0x00 0x00 0x00 0x01在内存中从高字节开始存放。

Java是big-endian还是little-endian?

Java默认采用big-endian方式,如各种读写流中的readInt()方法都是从高位到低位读取四个字节转化为整数。如果文件的读写都是通过Java来实现的,我们通常不需要去关注字节序的问题。但是如果与那些不是使用Java编写的程序交换数据文件时,就需要考虑字节序的问题了。

参考文献

周志明《深入理解Java虚拟机》
Big Endian 和 Little Endian 详解。原文链接:https://blog.csdn.net/waitingbb123/java/article/details/80504093

相关文章

  • Java格式工厂(一)——什么是二进制文件?

    前言 最近在用Java做一个文件格式转化的工具(github地址:https://github.com/lhing...

  • .CLASS文件

    java class 文件是对Java程序二进制文件格式的精确定义。每一个Java class文件都对一个Java...

  • 聊聊jvm之虚拟机执行子系统

    一、类文件 Java虚拟机不和包括java在内的任何语言绑定,它只于“Class文件”这种特定的二进制文件格式所关...

  • jar压缩文件是什么以及如何使用?

    jar是什么? jar格式文件是sun公司特为Java文件(含Java和class文件)定义的一种文件压缩格式,俗...

  • javassist文档翻译(一)

    1、读和写字节码 Javassist是一个处理Java字节码的库,java字节码是使用二进制格式存储在文件中的话,...

  • Java多线程-程序运行堆栈分析

    class文件内容 class文件包含JAVA程序执行的字节码;数据严格按照格式紧凑排列在class文件中的二进制...

  • 聊聊DevOps制品管理-不止是存储制品这么简单

    什么是制品? 制品是指由源码编译打包生成的二进制文件,不同的开发语言对应着不同格式的二进制文件;这些二进制文件通常...

  • 1.Java程序运行原理分析

    class文件内容class文件包含Java程序执行的字节码;数据严格按照格式紧凑排列在class文件中的二进制流...

  • 文件输入/输出

    文件内容和二进制内容:文本格式和二进制格式:文本模式和二进制模式:所有文件都是以二进制形式存储,但是如果文件最初使...

  • python利用numpy存取文件

    NumPy提供了多种存取数组内容的文件操作函数。保存数组数据的文件可以是二进制格式或者文本格式。二进制格式的文件又...

网友评论

    本文标题:Java格式工厂(一)——什么是二进制文件?

    本文链接:https://www.haomeiwen.com/subject/rojuohtx.html