javaI/O流小结
Posted PacosonSWJTU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javaI/O流小结相关的知识,希望对你有一定的参考价值。
【README】
1.本文总结java IO读取或写入数据的方式和相关类说明;
2.java IO建立在流之上的。输入流读取数据,输出流写入数据;
3.过滤器流-filter stream,可以串连(修饰)到输入流和输出流上;
4.补充:
- 补充1:java流操作数据的单位是字节;
- 补充2:流是同步的。 当程序请求一个流读写一段数据时,在做操作前,它要等待读写的数据到达或可用;
- 补充3:javaIO的实现方式还包括通道和缓存区的非阻塞IO;
5.阅读器reader或书写器writer,可以串链到输入流和输出流上,操作数据的单位是字符;
【1.1】java流
【1.1】java输入输出流基类(操作字节)
java基本输出流类是 OutputStream;写入字节;
java基本输入流类是 InputStream; 读取字节;
【1.2】过滤器流(操作字节,对字节加工或把字节转为字符)
1.过滤器基类是 FilterInputStream, FilterOutputStream;分别继承 InputStream, OuputStream;
2.过滤器分为2种:
- 过滤器流;过滤器流主要将原始数据作为字节处理;如压缩数据或解释为二进制数字;
- 阅读器和书写器;把不同编码格式的字节转为字符文本进行处理;
3.输入过滤器流 FilterInputStream 子类列表;
public
class FilterInputStream extends InputStream {
- DataInputStream;二进制读写数据;
- GZIPInputStream;压缩;
- HttpInputStream;支持http连接;
- TelnetInputStream;只是telnet连接;模拟客户端登录服务器协议;
- ZipInputStream; 压缩;
4.输出过滤器流 FilterOuputStream 子类;
public
class FilterOutputStream extends OutputStream {
- DataOutputStream;
- GZIPOutputStream;
- HttpSendOutputStream;
- TelnetOutputStream;
- ZipOutputStream;
5.多个过滤器流如何串链在一起处理字节流;
【1.2.1】多个过滤器链在一起
1.把 FileInputStream 和 BufferedInputStream 串链在一起
@Test
public void t1() throws Exception {
FileInputStream fis = new FileInputStream("D:\\\\temp\\\\hello5.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
}
【1.3】缓冲流(操作字节,缓冲)
1.分为输入缓冲流 BufferedInputStream, 输出缓冲流 BufferedOutputStream ;
2.缓冲流的作用:
- 2.1 对于输入缓冲流而言, 一次性不是读取一个字节,而是读取多个字节如1k个字节,减少磁盘io,提高读取性能;
- 2.2 对于输出缓冲流而言,一次性不是写入一个字节,而是写入多个字节如1k;特别对于网络连接,一次发送一个字节,每次报文头开销40字节,即每发送1个字节就会附加40个字节报文头,性能非常低下;若一次写入多个字节,则报文头开销占比会小很多,传输效率大大增加;
【1.4】PringStream(操作字节,丢弃)
PrintStream 是有害的;应该避开它;
- 问题1,因为 println() 的输出与平台有关;
- 问题2,PrintStream假定使用所在平台的默认编码方式;
- 问题3,printStream 吞掉所有异常;
【1.5】数据流(操作字节,二进制格式)
1.数据流基本类, DataInputStream, DataOutputStream ; 可以用二进制格式读写java基本数据类型和字符串;
try(DataOutputStream dataOutputStream = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("D:\\\\temp\\\\hello2.txt")))) {
dataOutputStream.write("hellworld2.这里是中国".getBytes(StandardCharsets.UTF_8));
}
【2】阅读器和书写器(操作字符)
1.阅读器和书写器, 操作数据的单位是字符而不是字节;
2.基类分别为 Reader, Writer ;
3.它们最重要的子类是 InputStreamReader 和 OutputStreamWriter类(依赖底层输入输出流);分别把字节转为字符进行读取,把字符转为字节进行写入; 可以在创建实例时指定字符编码方式,不用每次处理的时候都去指定编码方式
4.其他原始阅读器和书写器(不依赖底层输入输出流)
- FileReader
- FileWriter
- StringReader
- StringWriter
- CharArrayReader
- CharArrayWriter
// 书写器
try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
new BufferedOutputStream(new FileOutputStream("D:\\\\temp\\\\hello4.txt")), StandardCharsets.UTF_8)) {
outputStreamWriter.write("helloworld4.这里是中国");
}
// 阅读器
try (InputStreamReader inputStreamReader = new InputStreamReader(
new FileInputStream("D:\\\\temp\\\\hello4.txt"), StandardCharsets.UTF_8)) {
StringBuilder stringBuilder = new StringBuilder();
int c = 0;
while((c = inputStreamReader.read()) != -1) {
stringBuilder.append((char)c);
}
System.out.println();
System.out.println(stringBuilder.toString());
}
【2.1】过滤器阅读器和书写器
1,过滤器阅读器和书写器列表
- BufferedReader;缓冲读取器;
- BuffererWriter; 缓冲写入器;
- LineNumberReader;
- PushbackReader;
PrintWriter;(用于替换PrintStream,但也存在小问题)
2,BufferedReader
有1个readLine(),可以读取一行字符,并作为字符串返回;
try(BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(new FileInputStream("D:\\\\temp\\\\hello4.txt"), StandardCharsets.UTF_8))) {
String result = bufferedReader.readLine();
System.out.println(result);
}
【3】流关闭方式
1. 方式1, 通过 try-finally 块关闭; 把关闭流代码放在 finally 里面;
2.方式2,java7引入了 带资源的try构造方式,可以更简洁地完成流关闭;如下:
try(DataOutputStream dataOutputStream = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("D:\\\\temp\\\\hello2.txt")))) {
dataOutputStream.write("hellworld2.这里是中国".getBytes(StandardCharsets.UTF_8));
}
【3.1】如何优雅关闭流
1. 之所以使用带资源的try的构造方式新建的流可以自动关闭,其原因在于, 流实现了 AutoCloseable 接口, 如下:以 DataOutputStream 为例;
public
class DataOutputStream extends FilterOutputStream implements DataOutput {
...
public
class FilterOutputStream extends OutputStream {
...
public abstract class OutputStream implements Closeable, Flushable {
...
public interface Closeable extends AutoCloseable {
...
public interface AutoCloseable {
void close() throws Exception;
}
2. close方法如下实现的? 参见 FilterOutputStream.close() 方法 ; 所以它在关闭流的时候,会先刷新缓冲到底层流;
public void close() throws IOException {
try (OutputStream ostream = out) { // 这里其实也是一个 try资源块
flush();
}
}
public void flush() throws IOException {
out.flush();
}
3.我们再看下 AutoCloseable 的类说明如下:
一个可能持有资源(例如文件或套接字句柄)直到关闭的对象。 AutoCloseable 对象的 close() 方法在退出 try-with-resources 块时自动调用,该块已在资源规范标头中声明了该对象。 这种构造确保及时释放,避免资源耗尽异常和否则可能发生的错误。
API注意事项:即使不是所有的子类或实例都拥有可释放的资源,基类也有可能实现 AutoCloseable,而且实际上很常见。
对于必须完全通用的代码,或者当知道 AutoCloseable 实例需要资源释放时,建议使用 try-with-resources 构造。 但是,当使用 java.util.stream.Stream 等支持基于 I/O 和非基于 I/O 的形式时,使用非 I/O 时通常不需要 try-with-resources 块 - 基于形式。
【4】java IO流小结
【4.1】输入输出字节流类结构
【4.1.1】常用输入字节流类结构-InputStream
【4.1.2】常用输出字节流类结构-OutputStream
【4.2】输入输出字符流类结构
【4.2.1】常用输入字符流类结构-Reader
【4.2.2】常用输出字符流类结构-Writer
以上是关于javaI/O流小结的主要内容,如果未能解决你的问题,请参考以下文章
JavaI/O:简单的使用DataOutputStream和DataInputStream操作文件流
JavaI/O:简单的使用FileInput和FileOutputStream操作文件流
JavaI/O:简单的使用BufferedOutputStream和BufferedInputStr