java访问磁盘文件
转载,务必写上原文链接 !(尊重与你分享知识的人)
目录
文件
数据在磁盘中的唯一最小描述就是 文件 ,也就是说应用程序只能通过操控 文件 来操作磁盘上的数据;
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访问磁盘文件的更多相关文章
- java访问修饰符
了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...
- [THINKING IN JAVA]访问权限控制
6 访问权限控制 6.1 包:库单元 package.import.import *.import static: 修改classpath环境变量可以将自己写的类库添加至环境变量并在任何java程序中 ...
- java 访问 usb
java 要访问 usb 设备,通常要自己写c/c++代码,然后再用 java 访问这些组件,以达到控制usb设备的目的.但现在有一个开源组件 libusb 帮我们做好了访问usb设备的封装(包括wi ...
- Java访问USB设备
最近在用Java访问RDing设备,使用的是Java HID API.使用过程中发现一个问题,由于是嵌入式小白,不知道如何向USB设备发送report.于是想到可以看看自带的软件如何访问USB的.找到 ...
- java访问权限的问题
java访问权限的问题 java 访问权限 修饰符 背景: 关于java中的四种访问修饰符,public ,default ,protected ,private的作用范围本以为很熟悉了,但碰到了这样 ...
- Hadoop(五)搭建Hadoop与Java访问HDFS集群
前言 上一篇详细介绍了HDFS集群,还有操作HDFS集群的一些命令,常用的命令: hdfs dfs -ls xxx hdfs dfs -mkdir -p /xxx/xxx hdfs dfs -cat ...
- java访问权限修饰符
作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × × ja ...
- MinerQueue.java 访问队列
MinerQueue.java 访问队列 package com.iteye.injavawetrust.miner; import java.util.HashSet; import java.ut ...
- 论Java访问权限控制的重要性
人在什么面前最容易失去抵抗力? 美色,算是一个,比如说西施的贡献薄就是忍辱负重.以身报国.助越灭吴:金钱,算是另外一个,我们古人常说“钱乃身外之物,生不带来死不带去”,但我们又都知道“有钱能使鬼推磨” ...
随机推荐
- express中的中间件(middleware)、自定义中间件、静态文件中间件、路由中间件
express文档地址 什么是中间件呢(middleware)?它是谁的中间件呢? 首先我们需要了解到请求和响应, 请求就是客户端发送请求给服务器, 响应就是,服务器根据客户端的请求返回给客户端的数据 ...
- GFS中元数据的管理
GFS 元数据(metadata)中包含三部分: GFS元数据的管理方式: 1.文件的命名空间和块的命名空间: 采用持久化的方式. 对于文件和块的命名空间以及从文件到块的映射:通过向操作日志登记修改而 ...
- Go By Example-值类型
Go By Example-值类型 Go语言的数据类型可以分为值类型和引用类型,这里先说值类型. 值类型 值类型:在Go语言中int.float.bool和string这些类型都属于值类型,使用这些类 ...
- Cesium入门-1-展示一个地球
Cesium 官网教程地址 https://cesium.com/docs/tutorials/getting-started//tutorials/getting-started/ 第一个程序代码: ...
- BaggingClassifier
写在前面 Ensemble methods 组合模型的方式大致为四个:/bagging / boosting / voting / stacking ,此文主要简单叙述 bagging算法. 算法 ...
- Webpack中的sourcemap以及如何在生产和开发环境中合理的设置
一 . 从Sourcemap和Data URL说起 (1)什么是Sourcemap? 我们在打包中,将开发环境中源代码经过压缩,去空格,babel编译转化,最终可以得到适用于生产环境的项目代码,这样处 ...
- ArcGIS 10.5 tensorflow安装日记
ArcGIS 10.5 tensorflow安装日记 商务科技合作:向日葵,135-4855__4328,xiexiaokui#qq.com Datetime: 2019年5月27日星期一 Os: w ...
- Cookie的使用(js-cookie插件)
js-cookie 官方文档 里面就详细的介绍了es5怎么引用,以下是ES6以上的用户 一.安装 npm install js-cookie --save 二.引用 import Cookies fr ...
- 学习笔记——C++编程cin测试记录
cin读取输入流,遇到空格会暂停,下次继续读入剩下的,+++. #include <iostream> using namespace std; int main() { cout< ...
- mac下PHP安装mongo扩展
说明:mongo 和 mongodb是两个扩展,目前mongo扩展已经被废弃,建议使用mongodb扩展,但对于一些老项目还在使用mongo扩展的,请参考此文. mongodb和其他PHP扩展的安装方 ...