学习目的
了解java.io包的含义和作用
学会查看java.io包下类和接口的底层源码实现
掌握java.io包的常用接口和类,以及常用的方法
四、java.io
概念
通过数据流、序列化和文件系统提供系统输入和输出。流是java文件和计算机底层进行交流的一种方式、形式,计算机只认识二进制的补码。
流的形式
写入:硬盘文件-->译成字节码-->二进制流-->字节解码-->内存文件
写出:内存文件-->译成字节码-->二进制流-->字节解码-->硬盘文件
4.1 接口
接口
名称
备注
FileFilter
文件过滤器
掌握
Serializable
序列化
掌握
DataInput
数据读取
DataOutput
数据写出
ObjectInput
对象读取
掌握
ObjectOutput
对象写出
掌握
Closeable
资源关闭
Flush
刷新流
4.1.1 FileFilter文件过滤器
简述
用于抽象路径名的过滤器。
作用
常见实现类
底层实现及常用方法
@FunctionalInterface
public interface FileFilter {
//判断 指定抽象路径名 是否包含在某个调用者的路径名列表中
boolean accept(File pathname);
}
4.1.2 Serializable序列化
简述
类通过实现Serializable 接口,可以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
作用
实现Serializable接口的类都是可序列化类,可序列化类的所有子类型本身都是可序列化的。
常见实现类
底层实现及常用方法
//Serializable 接口没有方法或字段,仅用于标识可序列化的语义,只是一种规定
public interface Serializable {
}
4.1.3 DataInput数据读取
简述
字节形式读取,DataInput接口用于从二进制流中读取字节,并根据所有 Java 基本类型数据进行重构。
作用
将外部的文件通过二进制流读取成字节,jvm按照一定编码规则,将读取得到的字节编译成java的基本数据类型,形成java文件。
常见实现类
底层实现及常用方法
public interface DataInput {
//从输入流中读取字节,并将它们存储在缓冲区数组 b 中
void readFully(byte b[]) throws IOException;
//从输入流中读取 len长度个字节,off为起始偏移量
void readFully(byte b[], int off, int len) throws IOException;
//在输入流中跳过并丢弃n个字节数据,返回实际跳过的字节数
int skipBytes(int n) throws IOException;
//读取一个输入字节,若该字节不是零则返回 true,若是零则返回 false
boolean readBoolean() throws IOException;
//读取并返回一个输入字节,范围是 -128 到 127
byte readByte() throws IOException;
//读取一个输入字节并返回结果,范围是 0 到 255
int readUnsignedByte() throws IOException;
//读取两个输入字节
short readShort() throws IOException;
int readUnsignedShort() throws IOException;
char readChar() throws IOException;
//读取四个输入字节
int readInt() throws IOException;
float readFloat() throws IOException;
//读取八个输入字节
long readLong() throws IOException;
double readDouble() throws IOException;
//从输入流中读取下一文本行
String readLine() throws IOException;
//读入一个已使用UTF-8 修改版格式编码的字符串
String readUTF() throws IOException;
}
4.1.4 DataOutput数据写出
简述
字节形式写出,DataOutput接口用于 将数据从任意 Java基本类型 转换 为一系列字节,并将这些字节写入二进制流。
作用
类似于编译过的java文件的执行过程。将java编译后得到的字节码文件,翻译成字节形式,通过二进制流写入到外部文件中。
常见实现类
底层实现及常用方法
public interface DataOutput {
//将参数 b 的八个低位写入输出流
void write(int b) throws IOException;
//将数组 b 中的所有字节写入输出流
void write(byte b[]) throws IOException;
//将数组 b 中的 len 个字节按顺序写入输出流,off为起始偏移量
void write(byte b[], int off, int len) throws IOException;
//将一个 boolean 值写入输出流
void writeBoolean(boolean v) throws IOException;
//将参数 v 的八个低位写入输出流
void writeByte(int v) throws IOException;
//将两个字节写入输出流
void writeShort(int v) throws IOException;
//将一个 char字符写入输出流,该值由两个字节组成
void writeChar(int v) throws IOException;
//将一个 int 值写入输出流,该值由四个字节组成
void writeInt(int v) throws IOException;
void writeFloat(float v) throws IOException;
//将一个 long 值写入输出流,该值由八个字节组成
void writeLong(long v) throws IOException;
void writeDouble(double v) throws IOException;
//将一个字符串s写入输出流,每个字符用一个字节表示
void writeBytes(String s) throws IOException;
//将一个字符串s写入输出流,每个字符用两个字节表示
void writeChars(String s) throws IOException;
//将信息写入输出流,每个字符用UTF-8 格式编码的两个字节表示
void writeUTF(String s) throws IOException;
}
4.1.5 ObjectInput
简述
对象形式读取,ObjectInput 扩展了DataInput 接口,包含了对对象(引用数据类型)的读操作。DataInput 仅包括基本类型的输入方法;ObjectInput 扩展了该接口,以包含对象、数组和 String 的输出方法。
作用
常见实现类
底层实现及常用方法
public interface ObjectInput extends DataInput, AutoCloseable {
//读取并返回对象
public Object readObject() throws ClassNotFoundException, IOException;
//读取数据字节,返回读取的字节;若已到达流的末尾则返回 -1
public int read() throws IOException;
//读入 byte 数组,返回读取的实际字节数
public int read(byte b[]) throws IOException;
//从b数组中的off指定位移开始,读取len个长度的字节,返回读取的实际字节数
public int read(byte b[], int off, int len) throws IOException;
//跳过输入的 n 个字节,返回跳过的实际字节数
public long skip(long n) throws IOException;
//返回可以无阻塞读取 的字节数
public int available() throws IOException;
// 关闭输入流
public void close() throws IOException;
}
4.1.6 ObjectOutput
简述
对象形式写出,ObjectOutput 扩展了DataOutput 接口,包含了对对象(引用数据类型)的写入操作。DataOutput 包括基本类型的输出方法;ObjectOutput 扩展了该接口,以包含对象、数组和 String 的输出方法。
作用
常见实现类
底层实现及常用方法
public interface ObjectOutput extends DataOutput, AutoCloseable {
//将对象写入 底层存储或流
public void writeObject(Object obj) throws IOException;
//写入字节b;在实际写入字节前,此方法将阻塞
public void write(int b) throws IOException;
//写入 byte 数组,b[]是实际写入的数据;在实际写入字节前将发生阻塞
public void write(byte b[]) throws IOException;
//写入字节的子数组,从b数组中的off指定位移开始,写入len个长度
public void write(byte b[], int off, int len) throws IOException;
//刷新该流的缓冲,执行后将写入所有已缓冲的输出字节
public void flush() throws IOException;
//关闭该流
public void close() throws IOException;
}
4.1.7 Closeable
简述
Closeable意为可以关闭的数据源或目标,提供close() 方法,当流对象调用close() 方法时,可释放对象保存的资源。
作用
当所有的流操作完成时,都应该在finally中调用Closebale接口的close()方法来关闭流,释放资源。
常见实现类
底层实现及常用方法
public interface Closeable extends AutoCloseable {
//关闭流资源,调用该方法时可能会出异常,必须捕获处理
public void close() throws IOException;
}
4.1.8 Flush
简述
Flushable 意为可刷新数据的目标地,提供flush()刷新流方法;输出流对象调用 flush()方法时,将所有管道中的已缓冲输出 写入硬盘文件中。
作用
当所有的输出流完成输出时,都应在finally中先调用Flush接口的flush()方法将可能存在流管道中的数据全部刷新到硬盘文件中,避免数据丢失;然后调用Closebale接口的close()来关闭流,释放资源。
常见实现类
底层实现及常用方法
public interface Flushable {
//刷新缓冲流资源,调用该方法时可能会出异常,必须捕获处理
void flush() throws IOException;
}
4.2 常用类
类名
作用
备注
FileInputStream
文件字节输入
文件流,掌握
FileOutputStream
文件字节输出
掌握
FileReader
文件字符输入
FileWriter
文件字符输出
InputStreamReader
字节输入转字符
转换流
OutputStreamWriter
字节输出转字符
BufferedReader
缓冲字符输入
缓冲流
BufferedWriter
缓冲字符输出
BufferedInputStream
缓冲字节输入
BufferedOutputStream
缓冲字节输出
DataInputStream
数据字节输入
数据流
DataOutputStream
数据字节输出
PrintWriter
字符打印输出
标准流,掌握
PrintStream
字节打印输出
ObjectInputStream
字节对象输入
对象流,掌握
ObjectOutputStream
字节对象输出
掌握
4.2.1 File类
简述
File是 java文件和目录路径名 的抽象表示形式,通常都是指文件。
作用
常见父类或接口
底层实现及常用方法
public class File implements Serializable, Comparable
{
//
private static final FileSystem fs = DefaultFileSystem.getFileSystem();
//
private final String path;
//
private static enum PathStatus { INVALID, CHECKED };
//文件的路径状态
private transient PathStatus status = null;
//判断文件路径状态是否失效
final boolean isInvalid() {
if (status == null) {
status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED : PathStatus.INVALID;
}
return status == PathStatus.INVALID;
}
public static final char separatorChar = fs.getSeparator();
public static final String separator = "" + separatorChar;
public static final char pathSeparatorChar = fs.getPathSeparator();
public static final String pathSeparator = "" + pathSeparatorChar;
/* -- Constructors 构造方法-- */
//
private File(String pathname, int prefixLength) {
this.path = pathname;
this.prefixLength = prefixLength;
}
//
private File(String child, File parent) {
assert parent.path != null;
assert (!parent.path.equals(""));
this.path = fs.resolve(parent.path, child);
this.prefixLength = parent.prefixLength;
}
//
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}
//
public File(String parent, String child) {
if (child == null) {
throw new NullPointerException();
}
if (parent != null) {
if (parent.equals("")) {
this.path = fs.resolve(fs.getDefaultParent(), fs.normalize(child));
} else {
this.path = fs.resolve(fs.normalize(parent), fs.normalize(child));
}
} else {
this.path = fs.normalize(child);
}
this.prefixLength = fs.prefixLength(this.path);
}
//
public File(File parent, String child) {
if (child == null) {
throw new NullPointerException();
}
if (parent != null) {
if (parent.path.equals("")) {
this.path = fs.resolve(fs.getDefaultParent(), fs.normalize(child));
} else {
this.path = fs.resolve(parent.path, fs.normalize(child));
}
} else {
this.path = fs.normalize(child);
}
this.prefixLength = fs.prefixLength(this.path);
}
//
public File(URI uri) {
// Check our many preconditions
if (!uri.isAbsolute())
throw new IllegalArgumentException("URI is not absolute");
if (uri.isOpaque())
throw new IllegalArgumentException("URI is not hierarchical");
String scheme = uri.getScheme();
if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
throw new IllegalArgumentException("URI scheme is not \"file\"");
if (uri.getAuthority() != null)
throw new IllegalArgumentException("URI has an authority component");
if (uri.getFragment() != null)
throw new IllegalArgumentException("URI has a fragment component");
if (uri.getQuery() != null)
throw new IllegalArgumentException("URI has a query component");
String p = uri.getPath();
if (p.equals(""))
throw new IllegalArgumentException("URI path component is empty");
// Okay, now initialize
p = fs.fromURIPath(p);
if (File.separatorChar != '/')
p = p.replace('/', File.separatorChar);
this.path = fs.normalize(p);
this.prefixLength = fs.prefixLength(this.path);
}
/* -- Path-component accessors 路径-组件操作-- */
//
public String getName() {
int index = path.lastIndexOf(separatorChar);
if (index < prefixLength) return path.substring(prefixLength);
return path.substring(index + 1);
}
//
public String getParent() {
int index = path.lastIndexOf(separatorChar);
if (index < prefixLength) {
if ((prefixLength > 0) && (path.length() > prefixLength))
return path.substring(0, prefixLength);
return null;
}
return path.substring(0, index);
}
//
public File getParentFile() {
String p = this.getParent();
if (p == null) return null;
return new File(p, this.prefixLength);
}
//
public String getPath() {
return path;
}
/* -- Path operations 路径操作-- */
public boolean isAbsolute() {
return fs.isAbsolute(this);
}
public String getAbsolutePath() {
return fs.resolve(this);
}
public File getAbsoluteFile() {
String absPath = getAbsolutePath();
return new File(absPath, fs.prefixLength(absPath));
}
public String getCanonicalPath() throws IOException {
if (isInvalid()) {
throw new IOException("Invalid file path");
}
return fs.canonicalize(fs.resolve(this));
}
public File getCanonicalFile() throws IOException {
String canonPath = getCanonicalPath();
return new File(canonPath, fs.prefixLength(canonPath));
}
private static String slashify(String path, boolean isDirectory) {
String p = path;
if (File.separatorChar != '/')
p = p.replace(File.separatorChar, '/');
if (!p.startsWith("/"))
p = "/" + p;
if (!p.endsWith("/") && isDirectory)
p = p + "/";
return p;
}
@Deprecated
public URL toURL() throws MalformedURLException {
if (isInvalid()) {
throw new MalformedURLException("Invalid file path");
}
return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
}
public URI toURI() {
try {
File f = getAbsoluteFile();
String sp = slashify(f.getPath(), f.isDirectory());
if (sp.startsWith("//"))
sp = "//" + sp;
return new URI("file", null, sp, null);
} catch (URISyntaxException x) {
throw new Error(x); // Can't happen
}
}
/* -- Attribute accessors 属性操作-- */
public boolean canRead() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
if (isInvalid()) {
return false;
}
return fs.checkAccess(this, FileSystem.ACCESS_READ);
}
public boolean canWrite() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkWrite(path);
}
if (isInvalid()) {
return false;
}
return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
}
}
4.2.2
简述
作用
常见父类或接口
底层实现及常用方法
4.2.3
简述
作用
常见父类或接口
底层实现及常用方法
4.2.4
简述
作用
常见父类或接口
底层实现及常用方法
4.2.5
简述
作用
常见父类或接口
底层实现及常用方法
4.2.6
简述
作用
常见父类或接口
底层实现及常用方法
4.2.7
简述
作用
常见父类或接口
底层实现及常用方法
4.2.8
简述
作用
常见父类或接口
底层实现及常用方法
4.2.9
简述
作用
常见父类或接口
底层实现及常用方法