今天学习FileInputStream与FileOutputStream。
FileInputStream是文件输入流,用于从文件系统中的某个文件中获得输入字节。FileInputStream用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用FileReader。
FileOutputStream是文件输出流,用于将数据写入File或FileDescriptor的输出流。FileOutputStream用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用FileWriter。
FileInputStream
先学习下FileInputStream的源码。
public class FileInputStream extends InputStream
{
//FileInputStream的文件描述符
private final FileDescriptor fd;
//引用文件的路径
private final String path;
//文件通道
private FileChannel channel = null;
//关闭锁
private final Object closeLock = new Object();
//标识流是否关闭
private volatile boolean closed = false;
/**
* 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径名name指定。创建一个新FileDescriptor对象来表示此文件连接。
*
* 首先,如果有安全管理器,则用name作为参数调用其checkRead方法。
*
* @param name 文件系统中的路径名
* @exception FileNotFoundException 如果该文件不存在,或者它是一个目录,而不是一个常规文件,
* 抑或因为其他某些原因而无法打开进行读取。
*/
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
/**
* 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的File对象file指定。
*
* 参考FileInputStream(String name)的注释
*/
public FileInputStream(File file) throws FileNotFoundException {
//获取文件名
String name = (file != null ? file.getPath() : null);
//获取安全管理器
SecurityManager security = System.getSecurityManager();
if (security != null) {
//如果调用线程没有访问指定文件的权限,抛出SecurityException
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
//fd表示此文件连接
fd = new FileDescriptor();
fd.attach(this);
path = name;
//打开文件
open(name);
}
/**
* 通过使用文件描述符fdObj创建一个FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
*/
public FileInputStream(FileDescriptor fdObj) {
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
path = null;
fd.attach(this);
}
/*
* native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。
* Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
* JNI是Java本机接口(Java Native Interface),是一个本机编程接口,
* 它是Java软件开发工具箱(Java Software Development Kit,SDK)的一部分。
* JNI允许Java代码使用以其他语言编写的代码和代码库。
* Invocation API(JNI的一部分)可以用来将Java虚拟机(JVM)嵌入到本机应用程序中,
* 从而允许程序员从本机代码内部调用Java代码。
* 所以想要了解open0方法的具体实现只能去查看JVM源码了。
*/
private native void open0(String name) throws FileNotFoundException;
// wrap native call to allow instrumentation
/**
* Opens the specified file for reading.
* @param name the name of the file
*/
private void open(String name) throws FileNotFoundException {
open0(name);
}
/**
* 从此输入流中读取一个数据字节。
*/
public int read() throws IOException {
return read0();
}
/**
* 参考open0(String name)
*/
private native int read0() throws IOException;
/**
* 从此输入流中将最多len个字节的数据读入一个起始偏移量为off的byte数组中。
*
* 参考open0(String name)
*/