Skip to content

计算机原理:二进制与数据存储

计算机底层只处理二进制。数字、字符、图片、音频和视频最终都会转换为由 01 组成的数据。

bit、byte 与容量单位

计算机中的数据单位

bit(比特)是最小的信息单位,取值只有 01;8 个 bit 组成 1 个 byte(字节)。Java 中 int 的“4 字节”、long 的“8 字节”都是以 byte 为单位。

单位含义常见用途
bit / b一个二进制位网络带宽,如 100 Mbps
byte / B8 bit文件、内存、Java 类型大小
KBMBGBTB十进制单位,每级 1000 倍硬盘标称容量、网络
KiBMiBGiBTiB二进制单位,每级 1024 倍操作系统、程序运行环境
text
1 B = 8 b
1 KiB = 1024 B
1 MiB = 1024 KiB
1 GiB = 1024 MiB

日常交流常把 1 KB 说成 1024 B;严格来说,KB1000 BKiB 才是 1024 B。磁盘标称容量与系统显示容量不一致,通常就是单位口径不同。

字符、多媒体与文件数据

字符存储的是字符编码对应数字的二进制形式。ASCII 中常见字符的编码如下:

字符ASCII 数值二进制表示
A6501000001
a9701100001
04800110000

Java 的 char 使用 UTF-16 代码单元,因此字符范围不止 ASCII;A 的编码值恰好与 ASCII 相同。文本文件常用 UTF-8 编码。

文件的本质

文件本质上是一串字节。文本文件、图片、音频和视频的区别,不在于磁盘存储方式,而在于程序按照什么规则解释这些字节。

文件类型字节中主要保存的内容常见解析方式
文本文件字符编码后的字节按 UTF-8、GBK 等字符集解码
图片像素、颜色、尺寸和压缩数据PNG、JPEG 等图片解码器
音频采样数据或压缩后的音频帧MP3、AAC、WAV 等音频解码器
视频视频帧、音频、时间信息和编码数据容器解析后分别解码音视频轨道

文件开头通常包含格式标识和元数据,常被称为“文件头”或魔数。例如 PNG 文件以特定字节开头,程序据此判断如何解析。扩展名只是便于用户和系统识别的名称;把 photo.png 改为 photo.jpg 不会把 PNG 转成 JPEG,文件中的字节没有改变。

音频如何转换与播放

现实声音是连续信号,数字音频需要经过采样和量化:在固定时间间隔记录声音强度,再把强度转换为可存储的整数值。WAV 常用于保存接近原始的 PCM 采样数据;MP3、AAC 等编码格式会通过压缩减少体积。

text
声音信号 → 采样 → 量化 → PCM 数据 → 音频编码/压缩 → 音频文件
音频文件 → 解码 → PCM 数据 → 数模转换 → 扬声器播放

音频采样、量化与二进制编码

图左是连续的声音波形;图右将波形按固定时间点采样,再把每个采样点量化到有限等级。等级可以用二进制编码,例如 3 位可表示 000 ~ 111 共 8 个等级。连续的编码结果按字节写入文件,便形成 PCM 等数字音频数据。

采样率决定每秒记录多少次,例如 44.1 kHz 表示每秒采样 44100 次;位深影响每次采样可表示的精细程度。采样率、位深和声道数越高,通常音质与文件体积也越高。

视频如何转换与播放

视频可以理解为连续画面加上音频。原始视频每一帧都是大量像素数据,体积非常大,因此通常先使用 H.264、H.265、AV1 等视频编码器压缩;编码器会利用同一帧中的相似区域,以及相邻帧之间的变化来减少重复数据。

text
摄像头画面 → 视频帧 → 视频编码
麦克风声音 → 音频采样 → 音频编码
视频流 + 音频流 + 时间信息 → MP4 / MKV 等容器文件

MP4、MKV 是容器格式,负责组织音视频流、字幕和时间信息;H.264、AAC 等是编码格式,负责压缩和解码具体的音频或视频数据。播放器先解析容器,再解码各轨道,最后按时间戳同步播放。

二进制与十进制转换

进制只改变数值的表示形式。理解二进制与十进制之间的转换,是继续学习八进制、十六进制和 Java 整数字面量的基础。

二进制转十进制

从右向左,每一位乘以对应的 2 的幂,再求和。

二进制转十进制

text
0b10110 = 1 × 2⁴ + 0 × 2³ + 1 × 2² + 1 × 2¹ + 0 × 2⁰
        = 16 + 4 + 2
        = 22
java
public class BinaryValueDemo {
    public static void main(String[] args) {
        int value = 0b10110;
        System.out.println(value); // 22
    }
}

十进制转二进制

对十进制整数持续除以 2 并记录余数,直到商为 0;将余数从下往上读取。

text
22 ÷ 2 = 11 ··· 0
11 ÷ 2 =  5 ··· 1
 5 ÷ 2 =  2 ··· 1
 2 ÷ 2 =  1 ··· 0
 1 ÷ 2 =  0 ··· 1

结果:10110

八进制与十六进制

为了便于观察和表示二进制,常使用八进制和十六进制。Java 整数最终仍以二进制参与运算,100b10100xA 表示相同的数值。

进制基数Java 前缀示例十进制值
二进制20b0B0b101010
八进制8001210
十进制101010
十六进制160x0X0xA10

八进制与十六进制表示

java
public class RadixLiteralDemo {
    public static void main(String[] args) {
        int binary = 0b110;      // 6
        int octal = 0141;        // 97
        int hexadecimal = 0x61;  // 97
        int amount = 1_000_000;  // 下划线只用于提高可读性

        System.out.println(binary);      // 6
        System.out.println(octal);       // 97
        System.out.println(hexadecimal); // 97
        System.out.println(amount);      // 1000000
    }
}

Java 编译器会先把这些字面量转换为同一个整数值,运行时变量里不会保留“这是八进制还是十六进制”的信息。八进制以单个 0 开头,容易和普通数字混淆;除文件权限等明确场景外,更推荐使用十进制或十六进制。

二进制与八、十六进制

二进制每 3 位对应 1 位八进制,每 4 位对应 1 位十六进制;从右侧开始分组,不足时左侧补 0

二进制八进制十六进制十进制
110666
101012A10
11111111377FF255

十六进制中,A ~ F 分别表示十进制的 10 ~ 15。颜色值、字节码和内存地址中经常会看到十六进制。

Java 中的转换

Integer 提供了常用转换方法。字符串转数字时要明确传入原字符串的进制。

java
public class RadixConvertDemo {
    public static void main(String[] args) {
        int decimal = Integer.parseInt("1010", 2); // 10
        int hexValue = Integer.parseInt("FF", 16); // 255

        String binary = Integer.toBinaryString(10); // "1010"
        String octal = Integer.toOctalString(255);  // "377"
        String hex = Integer.toHexString(255);      // "ff"

        System.out.println(decimal);  // 10
        System.out.println(hexValue); // 255
        System.out.println(binary);   // 1010
        System.out.println(octal);    // 377
        System.out.println(hex);      // ff
    }
}

Integer.parseInt(text, radix) 将指定进制的字符串转为十进制整数;toBinaryStringtoOctalStringtoHexString 则将整数转为对应进制的字符串。

场景JavaJavaScript / TypeScript
二进制字面量0b10100b1010
八进制字面量012,不建议日常使用0o12
十六进制字面量0xFF0xFF
字符串转十进制Integer.parseInt("1010", 2)parseInt("1010", 2)
转二进制字符串Integer.toBinaryString(10)(10).toString(2)

小结

  1. 计算机底层以二进制存储数据,bit 表示一个 011 B = 8 b;容量单位要区分十进制的 KB 与二进制的 KiB
  2. 字符、图片、音频和视频最终都是二进制数据。字符需要依赖编码规则解释,Java char 使用 UTF-16 代码单元,文本文件常用 UTF-8;文件扩展名不会改变文件真实格式。
  3. 数字音频通过采样、量化、编码生成;视频由视频帧、音频和时间信息组成,通常先编码压缩,再封装到 MP4、MKV 等容器中。
  4. 二、八、十、十六进制是同一个数值的不同表示形式;Java 中分别使用 0b0、无前缀和 0x 书写整数字面量。
  5. 二进制转十进制使用按位权求和;十进制转二进制使用除二取余;二进制与八、十六进制之间可分别按 3 位和 4 位分组转换。
  6. 代码中可使用 Integer.parseInt(text, radix) 解析指定进制的字符串,使用 toBinaryStringtoOctalStringtoHexString 输出对应进制的字符串。
最近更新