文章目录

  • 背景
  • 示例
  • 前置条件
  • 使用 FileInputStream 流读取内容
  • 参数详解
  • 网上的错误解释
  • 正确的解释
  • 总结

 

背景

在使用Java的 IO过程中,肯定遇到过偏移量这个概念。网上也有很多人都解释过,但是有很多的人都被误导理解错了,也包括我。偏移量确实很容易理解错,刚开始我也理解错了。直到后来看BufferedOutputStream 源码的时候就越发感觉不对劲。

下面就详细解释一下偏移量到底什么意思。

在 FileInputStream 中的public int read(byte b[], int off, int len)方法中第二个参数,int off 就是偏移量的意思。

示例

前置条件

先在 F:\FilesExample\A.txt 文件中加入待读取的内容

ABCDEFG

 

使用 FileInputStream 流读取内容

public static void main(String[] args) {

    String filePath = "F:\\FilesExample\\A.txt";

    // 创建字节输入流
    try ( FileInputStream fis = new FileInputStream(filePath)){

        // 创建装数据的数组
        byte[] bytes = new byte[10];
        
		// 调用read方法读取数据
        fis.read(bytes, 2, 3);

		// 打印读出来的数据
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
        }
        
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意这句代码

fis.read(bytes, 2, 3);

 

注意这里的参数

  • 第一个参数是存放即将读出来的数据的字节数组。
  • 第二个参数是偏移量,这里先传个2。
  • 第三个参数是要读取的长度。

参数详解

第一个参数不用过多解释,就是存放数据的数组。

第二个参数代表偏移量,就是有歧义的地方。

网上的错误解释

偏移量的意思就是,读数据的时候从上一次读的最后位置接着往下读,比如第一次读了1024个字节,那么下一次就从1025开始读

 

这句话哪里错了?
这句话的意思是说,偏移量是数据流的偏移量。在上一次读到某个位置后,偏移量就记录下那个位置的坐标,下一次读取的时候,接着往后读。

如果按照这个意思来读取的话,我们传入的参数是2,也就是数据流的偏移量是2,那就该从下表为2的地方开始读,那应该跳过“A”,“B”两个字节,读取结果应该是”C“,”D“,”E“三个数据。

我们来运行一下,结果显示:

0
0
65
66
67
0
0
0
0
0

这里有两个地方需要注意一下

  1. 读取的字节都是ASCII码。 65代表大写字母”A“ ,66代表大写字母”B“,67代表大写字母”C“
  2. 字节数组空的位置会初始化成0。

结果和预想的完全不一样。(居然无论如何都是从数据流的最开始0下标开始读取,只不过存放在传入的数组位置变了)

正确的解释

其实偏移量 真正指的是这个存放数据的数组的偏移量(第一个参数)。

使用这个解释去理解一下这个示例。

读取3个字节(第三个参数)的数据,存放在bytes数组中(第一个参数),存放在数组中的什么位置呢?那就得看偏移量了,这里偏移量是2(第二个参数),就表示存放在数组中下标为2的位置开始,数据依次往后展开。也就是说,假设读取了两个字节的数据,就放在数组的3、4号坑(数组是从0开始的),假设读取了3个字节的数据,就放在数组的3、4、5号坑…

总结

Java IO流中的偏移量是指接收数据的数组(或叫缓冲区)的偏移量,并不是数据流的偏移量。