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


目录


文件

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


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. P5346 【XR-1】柯南家族(后缀数组+主席树)

    题目 P5346 [XR-1]柯南家族 做法 聪明性是具有传递性的,且排列是固定的 那么先预处理出每个点的名次,用主席树维护\(k\)大值 一眼平衡树,遍历的同时插入\(O(log^2n)\),总时间 ...

  2. Java学习日记——基础篇(二)基本语法

    变量 变量和常量是程序处理的两种基本数据对象,变量是程序的基本组成单位 变量的目的就是确定目标并提供存放空间 public class Hello { public static void main( ...

  3. MySQL表连接

    有3种: JOIN 按照功能大致分为如下三类: CROSS JOIN (交叉连接) INNER JOIN (内连接或等值连接). OUTER JOIN (外连接) 交叉连接CROSS JOIN 交叉连 ...

  4. 【代码】python 绘图(以faster rcnn 的 loss 曲线为例)

    # -*- coding=utf-8 -*-''' import matplotlib.pyplot as plt import re logs=open('loss').read() #print ...

  5. sql 分组后每组查询10个

    SELECT ID,Name,Class ROW_NUMBER() OVER(PARTITION BY Class ORDER BY ID) as NUM 主要是用到 rownum 里面的 PARTI ...

  6. 深入理解JVM虚拟机9:JVM监控工具与诊断实践

    转自https://juejin.im/post/59e6c1f26fb9a0451c397a8c jvm优化必知系列——监控工具 微信公众号[Java技术江湖]一位阿里 Java 工程师的技术小站. ...

  7. java maven scope compile,provide,system,test,runtime

    在一个maven项目中,如果存在编译需要而发布不需要的jar包,可以用scope标签,值设为provided.如下: <dependency>            <groupId ...

  8. Linux 使用 you-get 指令下载网页视频

    今天无意中发现一个下载网页视频的好办法 在 Linux 系统中,可以利用 you-get 指令直接下载网页中的视频 1.更新 sudo apt-get update 2.安装 pip sudo apt ...

  9. daoliu平台:测试线路图

    1.进行需求收集及分析 搜索关键字:导流平台 同类产品体验及熟悉 搞清楚,业务流.数据流.用户焦点 2.初步熟悉原型 初步熟悉.遍历原型, 初步进行测试需求分析 3.聆听及和权威的人进行沟通 测试人员 ...

  10. Java中运行动态脚本

    这里主要总结Java中集成Groovy的应用. Groovy可以与Java完美集成来扩展我们的应用,比如替代Java+jexl实现算式表达式计算或其它功能.在Ofbiz中也集成了Groovy来执行一些 ...