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


目录


文件

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


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. Unrecognized syntax identifier "proto3". This parser only recognizes "proto2". ”问题解决方法

    编译cartographer时遇到Unrecognized syntax identifier “proto3”. This parser only recognizes “proto2”.排查:使用 ...

  2. 用python实现不同格式99乘法表输出

    前言:学习python已经有一段时间了,最近发现有时候会出现一个东西知道,也能写出来,但是说不出来的情况.思考后觉得是基础还不够扎实,只一味写代码,没有深入思考具体实现的逻辑,以及各个点之间的关联.所 ...

  3. nodejs爬虫案例笔记

    用nodeJs制作一个简单的网页爬虫 主要分为三个步骤,向目标请求数据,处理数据,打印数据.需要用到的模块有http,cheerio. 1.准备步骤,引入要使用的模块 2.向目标请求数据 http.g ...

  4. 快速打造自己的PHPStorm主题

    ---恢复内容开始--- 一个优雅和舒适的界面,可以增加过多写入代码的动力. Phpstorm小型的白色主题比较简陋.为了打造一个优雅和舒适的界面,我们安装一件叫Material Theme UI的插 ...

  5. BZOJ3781小B的询问

    莫队裸题. 维护的时候有的打法是利用(a-1)^2==a^2-2*a+1转移,也可以,但是通用性不太够. 下面的打法就是先把这个点的贡献删掉,然后更新这个点,再把这个点的贡献加回来,这种解法更加通用一 ...

  6. 配置mysql远程访问

    参考: https://www.cnblogs.com/sanduzxcvbnm/p/9789236.html

  7. IdentityServer4入门四:应用Implicit模式保护网站(下)

    为认证服务端增加数据库支持 我计划使用一个名为Admin的表,放在一个已有的数据库里.所以我需要定义Admin类和在配置里预先加上数据库连接 新增类:Admin.cs public class Adm ...

  8. php手记之02-tp5请求参数读取三种方式

    01-[推荐方式] 当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息.在Thinkphp5.1中,获取请求对象数据,是由think\Request类负责,在很多场合下并不需 ...

  9. WindowsForm客户端自动更新逻辑

    启动客户端的时候,单独开一个线程,该线程主要是判断指定服务器上的更新包和本地使用的客户端是否一致,是否需要更新,不需要更新,则退出,需要更新则从服务端的下载更新包,然后提示用户是否更新,点击更新,启动 ...

  10. 记一次环境变量导致的elasticsearch启动错误:max file descriptors [65535] for elasticsearch process is too low, incre

    问题描述,elasticsearch启动时报max file descriptors错误: [hadoop@node-33 elasticsearch-5.4.0]$ bin/elasticsearc ...