转载,务必写上原文链接 !(尊重与你分享知识的人)


目录


文件

数据在磁盘中的唯一最小描述就是 文件 ,也就是说应用程序只能通过操控 文件 来操作磁盘上的数据;


File 对象 VS FileDescriptor 对象

初学 java IO 流的时候,基本都被告诉 java 里面用 File 来表示一个文件对象;

其实 File 并不代表一个真实存在的文件对象,当我们给定路径字符串的时候,返回的 File 对象仅仅是代表这个路径下的 虚拟对象,至于这个路径是一个文件还是一个文件夹,或者文件存在不存在,File 根本不关心 ;

只要当真正要读取这个文件的时候,才会检查给定路径的文件存在不存在(这个判断发生在读取流的构造器里面) ;

那么 java 里面,用什么来描述磁盘的文件 —— FileDescriptor 对象,它代表一个磁盘上的真实文件对象;


文件讲解java访问磁盘文件过程

// 创建一个字符读取流
FileReader fileReader = new FileReader("xxxxxx");

0、这一行代码后面都发生了什么事情;

我们要看下,这个 FileReader 到底是怎么工作的,跟进去看下源代码 ;


下面开始源码跟进分析


public FileReader(String fileName) throws FileNotFoundException {
// 调用父类构造器,传进去的参数是 FileInputStream
super(new FileInputStream(fileName));
}
----------------------------------------
// FileReader 的父类是 字节转换流
public class FileReader extends InputStreamReader

1、发现 FileReader 构造器中,是调用其父类 InputStreamReader 的构造器;

分析父类构造器参数发现,给父类构造器传递的参数是一个 FileInputStream 对象;我们同样需要看下这个类的构造器源代码;

public FileInputStream(String name) throws FileNotFoundException {
// 跟进传进来的字符串,创建对应的 虚拟对象 File
this(name != null ? new File(name) : null);
}

2、可以看见 FileInputStream 根据传进来的字符串,创建了 File 对象,然后将这个 File 对象,传给了同类的其他构造器

public FileInputStream(File file) throws FileNotFoundException {
// 获取文件的路径
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
// 如果name为null,说明传进来的file就是null。抛出空指针异常
if (name == null) {
throw new NullPointerException();
}
// 判断文件是否有效,也就是判断给File对象的路径下面的文件是否真的存在的;
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
// 创建一个代表真实文件的对象
fd = new FileDescriptor();
fd.incrementAndGetUseCount();
this.path = name;
// 打开路径下面的文件,是一个本地方法
open(name);
}

3、经过上面的代码分析,我们可以发现 FileInputStream 创建对象的时候,会对 File 构造器的路径参数进行检查,判断路径对应的文件到底存在与否;并且还会创建一个代表真实文件的 FileDescriptor 对象 ;

创建完 FileInputStream 对象以后,继续回到 FileReader 构造器上面 ;我们在上面的代码,知道 FileReader 是调用了父类 InputStreamReader 的构造器,现在我们关注一下它的父类构造器;

public FileReader(String fileName) throws FileNotFoundException {
// 调用父类构造器,传进去的参数是 FileInputStream
super(new FileInputStream(fileName));
} ----------------------------------------
public InputStreamReader(InputStream in) {
// 调用了父类构造器,里面没啥好看的,就加了锁
// 加锁的原因是因为,同一时刻一个文件只允许一个人来读取
super(in);
try {
// 创建一个 StreamDecoder 解码对象,将字节解码为字符
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}

4、查看源码,知道创建 InputStreamReader 对象,会同时创建 StreamDecoder 对象,因为我们是用字节流,最后需要的字符,所有需要它来解码

其中关于 StreamDecoder 笔者之前分析过—— StreamDecoder 对象分析(可点击)


fileReader.read()

分析完 上面,我们再看下 read()方法;看看到底是谁实现了read()接口 ;

 FileReader fileReader = new FileReader("xxxxxx");
// 跟进去看看 read()方法到底是谁实现的;
fileReader.read();
---------------------------------
// 跟进去发现是调用了 一个 sd变量的read方法;
public int read() throws IOException {
return sd.read();
}
-------------------------------------
// sd的read()方法实现
private int read0() throws IOException {
Object var1 = this.lock;
synchronized(this.lock) {
if (this.haveLeftoverChar) {
this.haveLeftoverChar = false;
return this.leftoverChar;
} else {
char[] var2 = new char[2];
int var3 = this.read(var2, 0, 2);
switch(var3) {
case -1:
return -1;
case 0:
default:
assert false : var3; return -1;
case 2:
this.leftoverChar = var2[1];
this.haveLeftoverChar = true;
case 1:
return var2[0];
}
}
}
} ---------------------------------
// 跟进发现 这个sd 是StreamDecoder 对象
private final StreamDecoder sd;

至此,我们发现底层工作都是 StreamDecoder 完成的,这个在背后默默工作的低调者,我们应该记住它;


图解java访问磁盘文件过程


java访问磁盘文件的更多相关文章

  1. java访问修饰符

    了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...

  2. [THINKING IN JAVA]访问权限控制

    6 访问权限控制 6.1 包:库单元 package.import.import *.import static: 修改classpath环境变量可以将自己写的类库添加至环境变量并在任何java程序中 ...

  3. java 访问 usb

    java 要访问 usb 设备,通常要自己写c/c++代码,然后再用 java 访问这些组件,以达到控制usb设备的目的.但现在有一个开源组件 libusb 帮我们做好了访问usb设备的封装(包括wi ...

  4. Java访问USB设备

    最近在用Java访问RDing设备,使用的是Java HID API.使用过程中发现一个问题,由于是嵌入式小白,不知道如何向USB设备发送report.于是想到可以看看自带的软件如何访问USB的.找到 ...

  5. java访问权限的问题

    java访问权限的问题 java 访问权限 修饰符 背景: 关于java中的四种访问修饰符,public ,default ,protected ,private的作用范围本以为很熟悉了,但碰到了这样 ...

  6. Hadoop(五)搭建Hadoop与Java访问HDFS集群

    前言 上一篇详细介绍了HDFS集群,还有操作HDFS集群的一些命令,常用的命令: hdfs dfs -ls xxx hdfs dfs -mkdir -p /xxx/xxx hdfs dfs -cat ...

  7. java访问权限修饰符

    作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × × ja ...

  8. MinerQueue.java 访问队列

    MinerQueue.java 访问队列 package com.iteye.injavawetrust.miner; import java.util.HashSet; import java.ut ...

  9. 论Java访问权限控制的重要性

    人在什么面前最容易失去抵抗力? 美色,算是一个,比如说西施的贡献薄就是忍辱负重.以身报国.助越灭吴:金钱,算是另外一个,我们古人常说“钱乃身外之物,生不带来死不带去”,但我们又都知道“有钱能使鬼推磨” ...

随机推荐

  1. 【零基础】神经网络优化之dropout和梯度校验

    一.序言 dropout和L1.L2一样是一种解决过拟合的方法,梯度检验则是一种检验“反向传播”计算是否准确的方法,这里合并简单讲述,并在文末提供完整示例代码,代码中还包含了之前L2的示例,全都是在“ ...

  2. 本周JavaScript学习小结

    应组长杨老师号召,写个js阶段性学习小结. emmm这周学了Linux进程通讯,学正则表达式尝试完成第一次编程作业,中秋还去平潭露营(所以...js学得很少hhh). 现在还处于感性认识阶段,浏览了一 ...

  3. Cesium入门-2-增加地形

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Path.Combine Method

    https://docs.microsoft.com/en-us/dotnet/api/system.io.path.combine?view=netframework-4.8#System_IO_P ...

  5. 【Oracle/Java】给十六张表各插入十万条数据 单线程耗时半小时 多线程耗时一刻钟

    测试机Oracle版本: SQL> select * from v$version; BANNER ----------------------------------------------- ...

  6. OpenJudge计算概论-分离整数的各个数位

    /*================================================================= 分离整数的各个数位 总时间限制: 1000ms 内存限制: 65 ...

  7. python 设计模式之命令(Command)模式

    #写在前面 也了解了不少设计模式了,他们都有一个通病,那就是喜欢把简单的东西复杂化.比如在不同的类中加个第三者.哈哈哈,简单变复杂是有目的的,那就是降低耦合度,增强可维护性,提高代码复用性,使代码变得 ...

  8. Android:导入所需的系统jar包到Android studio

    1. 修改对于的AIDL文件,根据编译信息获知所需的jar包. mmm /frameworks/base/ show commands > log.txt 2>&1 out/tar ...

  9. OGG-01332 ogg高版本向低版本传输

    Neo君遇到的ogg版本问题,在ggserr.log中的错误信息如下: 2018-10-12 09:55:10 ERROR OGG-01332 Oracle GoldenGate Delivery, ...

  10. MySQL数据库之sql_mode解释

    在MySQL5.6中,默认的SQL模式为:NO_ENGINE_SUBSTITUTION, 而在MySQL5.7中默认的SQL模式为:ONLY_FULL_GROUP_BY, STRICT_TRANS_T ...