java I/O知识点总结
程序员文章站
2024-03-03 19:25:28
...
I/O 字节、字符流接口简介
类 | 说明 |
---|---|
File | 文件类,代表一个特定文件信息,或代表一个目录下的一组文件, 常用方法getName、length、canRead、canWrite、getPath、exists、list、mkdirs、delete等方法 |
InputStream | 字节输入流接口,表示从不同数据源产生输入的类 |
OutputStream | 字节输出流接口,表示数据输出的目标 |
Reader | 字符输入流接口 |
Writer | 字符输出流接口 |
字符流是对文本内容高效操作的流对象。本质是基于字节流读取时,根据字符编码转化对应的文本内容。
File类使用实例
// 运用File.list的策略模式,返回文件名小于5字符的文件组
public class DirList {
public static void main(String[] args) {
File path = new File(".");
System.out.println("绝对路径: " + path.getAbsolutePath());
System.out.println("可读写: " + path.canRead() + " " + path.canWrite());
System.out.println("文件名: " + path.getName());
System.out.println("最后修改时间: " + path.lastModified());
String[] list = path.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.length() < 5 ? true : false;
}
});
for (String s : list) {
System.out.println(s);
}
}
}
字节流结构图
字节输入流
类 | 功能 | 构造参数 |
---|---|---|
InputStream | 抽象类,是所有的输入字节流的父类 | |
ByteArrayInputStream | 从缓冲区(内存)中读取数据 | byte[] |
FileInputStream | 从本地文件中读取数据 | File对象、文件名字符串、或FileDescriptor对象 |
FilterInputStream | 抽象类,作为“装饰器”的接口,为InputStream类提供更丰富的功能 | |
BufferedInputStream | FilterInputStream子类,使用缓冲区进行读取数据 | InputStream对象,可指定缓冲区大小 |
DataInputStream | FilterInputStream子类,与DataOutputStream搭配使用,可按照要求读取基本数据类型(int、char、long等) | InputStream对象 |
PushbackInputStream | FilterInputStream子类,查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分 | InputStream对象 |
LineNumberInputStream @Deprecated已弃 | FilterInputStream子类,可以跟踪流中的行号 | InputStream对象 |
PipedInputStream | 多线程之间管道通信 | PipedOutputStream对象 |
ObjectInputStream | ”装饰流”,用于java序列化支持 | InputStream对象 |
SequenceInputStream | 一个工具类,将两个或者多个输入流当成一个输入流依次读取 | 两个InputStream对象、或一个容纳InputStream对象的容器Enumeration |
StringBufferInputStream @Deprecated已弃 | 从字符串中读取数据,底层实现使用StringBuffer | String对象 |
字节输出流
类 | 功能 | 构造参数 |
---|---|---|
OutputStream | 抽象类,是所有的输出字节流的父类 | |
ByteArrayOutputStream | 将流信息写入向缓冲区(内存byte数组) | byte[],大小可选 |
FileOutputStream | 将流信息写入文件 | File对象、文件名字符串、或FileDescriptor对象 |
FileOutputStream | 抽象类,作为“装饰器”的接口,为OutputStream类提供更丰富的功能 | |
BufferedOutputStream | FilterOutputStream子类,使用缓冲区进行写入,避免每次发送数据时都要进行实际的写操作(只有缓冲区满时才进行实际的写入操作),flush()清空缓冲区 | OutputStream对象,可指定缓冲区大小 |
DataOutputStream | FilterOutputStream子类,与DataInputStream搭配使用,可以向流中写入基本的类型数据(int、char、long等) | InputStream对象 |
PrintStream | FilterOutputStream子类,用于产生格式化的输出,其中DataOutputStream处理数据存储,PrintStream处理显示,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具,System.out和System.err就是PrintStream的实例 | OutputStream对象 |
PipedOutputStream | 任何写入其中的信息自动作为相关PipedInputStream的输出,实现管道概念 | PipedInputStream对象 |
ObjectOutputStream | ”装饰流”,用于java序列化支持 | OutputStream对象 |
字节流使用实例
// An highlighted block
public class StoringAndRecoveringData {
public static void main(String[] args)
throws IOException {
DataOutputStream out = new DataOutputStream( // 搭配装饰器,支持基本类型的操作
new BufferedOutputStream( // 使用缓存装饰器
new FileOutputStream( // 以文件流为目标写入文件
new File("data.txt").getAbsoluteFile()))); // getAbsoluteFile()的作用是在报错时,可显示报错文件的绝对路径
out.writeDouble(3.14159);
out.writeUTF("That was pi");
out.close();
DataInputStream in = new DataInputStream( // 与DataOutputStream搭配,支持基本类型的操作
new BufferedInputStream( // 使用缓存装饰器
new FileInputStream( // 从本地文件数据源读取数据
new File("data.txt").getAbsoluteFile())));
System.out.println(in.readDouble());
System.out.println(in.readUTF());
in.close();
}
}
/* output:
3.14159
That was pi
*/
字符流结构图
字符输入流
类 | 功能 | 构造参数 |
---|---|---|
Reader | 抽象类,是所有的输入字符流的父类 | |
CharArrayReader | 从char[]中读取数据 | char[] |
StringReader | 从String中读取数据 | String对象 |
InputStreamReader | InputStream到Reader转换的桥梁 | InputStream对象 |
FileReader | InputStreamReader的子类,以字符流读取文件信息常用工具类,将FileInputStream 转变为Reader 的方法 | File对象、文件名字符串、或FileDescriptor对象 |
PipedReader | 多线程之间管道通信 | PipedWriter对象 |
FilterReader | 抽象类,作为“装饰器”的接口,为Reader类提供更丰富的功能 | |
PushbackReader | FilterReader子类,对Reader对象进行装饰,会增加一个行号 | Reader对象 |
BufferedReader | 装饰Reader对象,使用BufferedReader.readLine()是有效的读取行操作的方法 | Reader对象 |
LineNumberReader | BufferedReader子类,对Reader对象进行装饰,可获取行信息 | Reader对象 |
字符输出流
类 | 功能 | 构造参数 |
---|---|---|
Writer | 抽象类,是所有的输出字符流的父类 | |
CharArrayWriter | 向char[]中写入数据 | char[] |
StringWriter | 向String中写入数据 | String对象 |
OutputStreamWriter | OutputStream到Writer转换的桥梁 | OutputStream对象 |
FileWriter | OutputStreamWriter的子类,向文件写入字符流的常用工具类,将FileOutputStream 转变为Writer 的方法 | File对象、文件名字符串、或FileDescriptor对象 |
PipedWriter | 多线程之间管道通信 | PipedReader对象 |
FilterWriter | 抽象类,作为“装饰器”的接口,为Writer类提供更丰富的功能,没子类 | |
BufferedWriter | 装饰Writer对象,提供缓冲功能 | Writer对象 |
PrintWriter | 与PrintStream类似 | Writer对象 |
InputStreamReader可以把InputStream转换为Reader
OutputStreamWriter可以把OutputStream转换为Writer
字符流使用实例
public class BasicFileOutput {
static String file = "BasicFileOutput.out";
public static void main(String[] args)
throws IOException {
BufferedReader in = new BufferedReader(
new StringReader("hello world"));
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter(file)));
int lineCout = 1;
String s;
while ((s = in.readLine()) != null) {
out.println(lineCout++ + ": " + s);
}
out.close();
}
}
RandomAccessFile类
RandomAccessFile封装了字节流,同时还封装了一个缓冲区(字符数组),可以认为他是DataInputStream和DataOutputStream的整合。 该对象特点:
- 该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。
- 该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r、rw)。
注意:该对象在实例化时,如果操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。
RandomAccessFile使用实例
// 比较nio与普通io的速度
public class MapperIO {
private static int numOfInts = 400000;
private static int numOfUbuffInts = 200000;
private abstract static class Tester {
private String name;
public Tester(String name) {
this.name = name;
}
public void runTest() {
System.out.print(name + ": ");
try {
long start = System.nanoTime();
test();
double duration = System.nanoTime() - start;
System.out.format("%.2f\n", duration/1.0e9);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public abstract void test() throws IOException;
}
private static Tester[] tests = {
new Tester("Stream Write") {
@Override
public void test() throws IOException {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(new File("temp.tmp"))));
for(int i = 0; i < numOfInts; i++) {
dos.writeInt(i);
}
dos.close();
}
} , new Tester("Mapped Write") {
@Override
public void test() throws IOException {
FileChannel fc =
new RandomAccessFile("temp.tmp", "rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();
for(int i = 0; i < numOfInts; i++) {
ib.put(i);
}
fc.close();
}
},
new Tester("Stream Read") {
@Override
public void test() throws IOException {
DataInputStream dis = new DataInputStream(
new BufferedInputStream(new FileInputStream("temp.tmp")));
for(int i = 0; i < numOfInts; i++) {
dis.readInt();
}
dis.close();
}
}, new Tester("Mapped Read") {
@Override
public void test() throws IOException {
FileChannel fc =
new RandomAccessFile("temp.tmp", "rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();
while (ib.hasRemaining()){
ib.get();
}
fc.close();
}
}, new Tester("System Read/Write") {
@Override
public void test() throws IOException {
RandomAccessFile fc =
new RandomAccessFile("temp.tmp", "rw");
fc.writeInt('a');
for(int i = 0; i < numOfUbuffInts; i++) {
fc.seek(i*4);
fc.writeInt(fc.readInt());
}
fc.close();
}
},
new Tester("Mapped Read/Write") {
@Override
public void test() throws IOException {
FileChannel fc =
new RandomAccessFile("temp.tmp", "rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();
ib.put('b');
for(int i = 1; i < numOfUbuffInts; i++) {
ib.put(ib.get(i-1));
}
fc.close();
}
}
};
public static void main(String[] args) {
// 测试文件映射和IO操作性能
for (Tester test : tests) {
test.runTest();
}
}
}
/*output:
Stream Write: 0.03
Mapped Write: 0.01
Stream Read: 0.04
Mapped Read: 0.01
System Read/Write: 2.46
Mapped Read/Write: 0.01
* */
序列化实例
java序列化支持有ObjectOutputStream和ObjectInputStream支持
public class Logon implements Serializable {
private Date date = new Date();
private String username;
private transient String password; // transient关键之表示序列化时不保存该字段信息
public Logon(String name, String pwd) {
username = name;
password = pwd;
}
@Override
public String toString() {
return "logon info: \n username: " + username +
"\n date: " + date + "\n password: " + password;
}
public static void main(String[] args) throws Exception {
Logon a = new Logon("Hulk", "myLittlePony");
System.out.println("logon a = " + a) ;
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("Logon.out"));
o.writeObject(a);
o.close();
TimeUnit.SECONDS.sleep(3);
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Logon.out"));
System.out.println("Recovering object at " + new Date());
a = (Logon) in.readObject();
System.out.println("logon a = " + a) ;
}
}
/*output:
logon a = logon info:
username: Hulk
date: Thu Jan 31 17:02:54 CST 2019
password: myLittlePony
Recovering object at Thu Jan 31 17:02:57 CST 2019
logon a = logon info:
username: Hulk
date: Thu Jan 31 17:02:54 CST 2019
password: null
*/
- 如果需要特定的序列化规则,可以实现Externalizable接口,根据自定义的规则重写writeExternal(ObjectOutput)和 readExternal(ObjectInput)方法。
详细使用方式请查看jdk文档
——————>nio博客地址<——————
☀>.freerme[https://blog.csdn.net/freerme]