流式 IO 是传统 IO,通过构造输入输出流,讲信息从一个地方读取,输出到另一个地方。常见的有读取文件以及写入文件。

基本 API

流失 IO 基本可以分为两个门派,一个以 InputStream 和 OutputStream 为代表的老牌 IO,一个以 Reader 和 Writer 为代表的新派 IO。

这里仅仅展示最常用 API,其余 API 可以查阅jdk API

输入

基本输入

InputStream Reader
InputStream 面向字节流 IO 不能很好的支持 Unicode 字符 Reader 面向字符流 IO 能很好的支持 Unicode 字符
FileInputStream 文件读取流 FileReader 文件读取
ByteArrayInputStream CharArrayReader

装饰器输入

基本输入中的流对象,都可以作为装饰器对象的构造器参数

InputStream Reader 功能
DataInputStream 包含用于读取基本数据类型的全部接口
BufferedInputStream BufferedReader 本质上不提供接口,只是向进程添加缓冲功能。与接口对象搭配

输出

基本输出

OutputStream Writer
FileOutputStream FileWriter
ByteArrayOutputStream CharArrayWriter

装饰器输出

OutputStream Writer 功能
DataOutputStream 包含用于写入基本数据类型的全部接口
PrintStream PrintWriter 用于产生格式化输出
BufferedOutputStream BufferedWriter 本质上并不提供接口,只是向进程添加缓冲功能。与接口对象搭配

常见用法

读取文件

使用 FileInputStream 读取

下面例子将输入流放入 try-with-resource 块中,以实现资源的自动关闭,本文下面例子都将采用这种形式。

这里可以看到,是一个字节一个字节的读,所以要将其转为 char 才能正常展示,否则展示的都是字节。 由于 InputStream 是字节流,因此,这里读取到的中文展示乱码。

public class Read {
/**
* 使用 FileInputStream 直接读取
* 由于 InputStream 不支持 Unicode 编码,所以中文显示会乱码
*/
public static void fileInputStream() {
try (
FileInputStream input = new FileInputStream("Read.java")
) {
int n = 0;
while (n != -1) {
n = input.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileInputStream();
}
}

输出:

package cyrus.file_io.iostream;

import java.io.FileInputStream;

public class Read {
/**
* 使用 FileInputStream 直接读取
* 由于 InputStream 不支持 Unicode ç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–‡æ˜¾ç¤ºä¼šä¹±ç 
*/
public static void fileInputStream() {
try (
FileInputStream input = new FileInputStream("Read.java")
) {
int n = 0;
while (n != -1) {
n = input.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileInputStream();
}
}

使用 BufferedInputStream 装饰器读取

以下例子使用 FileInputStream 构造一个 BufferedInputStream 装饰器,该适配器的主要作用是会将读取到的内容填充进缓冲区,其余用法和 FileInputStream 一样。InputStream 是字节流,因此,这里读取到的中文展示乱码。

public class Read {
/**
* 使用 FileInputStream 构造一个 BufferedInputStream 装饰器,读取,该读取会使用缓冲区
* 由于 InputStream 不支持 Unicode 编码,所以中文会乱码
*/
public static void fileInputStreamWithBuffer() {
try (
BufferedInputStream input = new BufferedInputStream(new FileInputStream("Read.java"))
) {
int n = 0;
while (n != -1) {
n = input.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileInputStreamWithBuffer();
}
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.FileInputStream; public class Read {
/**
* 使用 FileInputStream æž„é€ ä¸€ä¸ª BufferedInputStream 装饰器,读取,该读取会使用缓冲区
* 由于 InputStream 不支持 Unicode ç¼–ç ï¼Œæ‰€ä»¥ä¸­æ–‡ä¼šä¹±ç 
*/
public static void fileInputStreamWithBuffer() {
try (
BufferedInputStream input = new BufferedInputStream(new FileInputStream("Read.java"))
) {
int n = 0;
while (n != -1) {
n = input.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileInputStreamWithBuffer();
}
}

使用 FileReader 进行读取

使用 FileReader 直接读取,这里 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示

public class Read {
/**
* 使用 FileReader 直接读取
* 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
*/
public static void fileReader() {
try (
FileReader reader = new FileReader("Read.java")
) {
int n = 0;
while (n != -1) {
n = reader.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileReader();
}
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileReader; public class Read {
/**
* 使用 FileReader 直接读取
* 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
*/
public static void fileReader() {
try (
FileReader reader = new FileReader("Read.java")
) {
int n = 0;
while (n != -1) {
n = reader.read();
char c = (char) n;
System.out.print(c);
}
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileReader();
}
}

使用 BufferedReader 装饰器读取

这里使用 FileReader 构造一个 BufferedReader 装饰器,BufferedReader 的主要作用是会将读取到的内容填入缓冲区,并且 BufferedReader 的 lines() 方法将返回一个 stream 流,操作更方便。

public class Read {
/**
* 使用 FileReader 构造一个 BufferedReader 装饰器,读取,该读取会使用缓冲区
* 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
*/
public static void fileReaderWithBuffer() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
reader.lines().forEach(System.out::println);
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileReaderWithBuffer();
}
}

输出:

package cyrus.file_io.iostream;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader; public class Read {
/**
* 使用 FileReader 构造一个 BufferedReader 装饰器,读取,该读取会使用缓冲区
* 由于 Reader 支持 Unicode 编码,因此中文不会乱码,正常显示
*/
public static void fileReaderWithBuffer() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
reader.lines().forEach(System.out::println);
} catch (Exception e) { }
} public static void main(String[] args) {
Read.fileReaderWithBuffer();
}
}

使用 DataInputStream 适配器读取字符串

这里 buildString() 方法读取当前文件,将其拼装为字符串输出,ByteArrayInputStream 读取该字符串的 byte 数组,然后转化为 DataInputStream 适配器进行读取字符串内容。

DataInputStream 主要用于读取基本数据类型

public class Read {
/**
* 使用 ByteArrayInputStream 构造 DataInputStream 装饰器,输出字符串信息
*/
public static void dataInputStream() {
try (
DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(buildString().getBytes()))
) {
while (inputStream.available() != 0) {
System.out.print((char) inputStream.readByte());
}
} catch (Exception e) { }
} /**
* 通过目前 java 文件构建一个字符串
*
* @return
*/
public static String buildString() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (Exception e) { }
return "ok";
} public static void main(String[] args) {
Read.dataInputStream();
}
}

写入文件

使用 FileOutputStream 写入

这里直接使用 FileOutputStream 读取 buildString() 方法构造的字符串并将其写入 Read.txt 文件

public class Read {
/**
* 使用 FileOutputStream 直接写入字符串
*/
public static void fileOutputStream() {
try (
FileOutputStream output = new FileOutputStream("Read.txt")
) {
output.write(buildString().getBytes());
} catch (Exception e) { }
}
/**
* 通过目前 java 文件构建一个字符串
*
* @return
*/
public static String buildString() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (Exception e) { }
return "ok";
} public static void main(String[] args) {
Read.fileOutputStream();
}
}

输出:实例截图一部分

使用 BufferedOutputStream 适配器写入

这里使用 FileOutputStream 构造一个 BufferedOutputStream 适配器,BufferedOutputStream 会使用到缓冲区,加快读取写入速度。

public class Read {
/**
* 使用 FileOutputStream 构造一个 BufferedOutputStream 装饰器,读取,该写入会使用缓冲区
*/
public static void fileOutputStreamWithBuffer() {
try (
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("Read.txt"));
) {
output.write(buildString().getBytes());
} catch (Exception e) { }
}
/**
* 通过目前 java 文件构建一个字符串
*
* @return
*/
public static String buildString() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (Exception e) { }
return "ok";
} public static void main(String[] args) {
Read.fileOutputStreamWithBuffer();
}
}

后面就不展示输出了,所有的输出都是输出到当前工作目录的Read.txt文件夹下,并且文件内容都是当前 .java 文件的内容

使用 FileWriter 写入

public class Read {
/**
* 使用 FileWriter 直接写入
*/
public static void fileWriter() {
try (
FileWriter writer = new FileWriter("Read.txt");
) {
writer.write(buildString());
} catch (Exception e) { }
}
/**
* 通过目前 java 文件构建一个字符串
*
* @return
*/
public static String buildString() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (Exception e) { }
return "ok";
} public static void main(String[] args) {
Read.fileWriter();
}
}

使用 PrintWriter 进行输出

这里使用了两层适配器,第一层是使用 FileWriter 构造一个 BufferedWriter,该适配器会使用缓冲区进行写入,然后再使用 BufferedWriter 构造一个PrintWriter 适配器,使用该适配器的println()方法直接输出到指定文件。

public class Read {
/**
* 使用 FileWriter 构造一个 BufferedWriter 装饰器,该装饰器会使用缓冲区,然后再使用 BufferedWriter 构造一个 PrintWriter装饰器,使用 println 输出到文件
*/
public static void fileWriterWithBuffer() {
try (
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("Read.txt")))
) {
writer.println(buildString());
} catch (Exception e) { }
}
/**
* 通过目前 java 文件构建一个字符串
*
* @return
*/
public static String buildString() {
try (BufferedReader reader = new BufferedReader(new FileReader("Read.java"))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (Exception e) { }
return "ok";
} public static void main(String[] args) {
Read.fileWriterWithBuffer();
}
}

总结

流式IO 其实挺好理解的,一共分为两套,InputStream、OutputStream 为一套,Reader 和 Writer 为一套,其中各自都有基本输入输出类和使用基本输入输出类构造的装饰器输入输出类,装饰器还能构造装饰器,无限套娃。

如 new PrintWriter(new BufferedWriter(new FileWriter("Read.txt"))),这里就将 BufferedWriter 装饰器装配成了 PrintWriter 装饰器,这样这个 PrintWriter 就拥有了 BufferedWriter 的特性(使用缓冲区),以及他自己的特性。

文章为本人学习过程中的一些个人见解,漏洞是必不可少的,希望各位大佬多多指教,帮忙修复修复漏洞!!!

参考资料:java 编程思想

欢迎进入本人语雀文档阅读,格式更清晰哦:

https://www.yuque.com/docs/share/26bf2f91-b3d3-4b28-a43e-302a1e650d57?# 《流式 IO》

简单易懂讲IO的更多相关文章

  1. 简单聊下IO复用

    没图,不分析API Java中IO API的发展:Socket -> SocketChannel -> AsynchronousSocketChannelServerSocket -> ...

  2. 【repost】让你一句话理解闭包(简单易懂)

    接触javascript很久了,每次理解闭包都似是而非,最近在找Web前端的工作,所以需要把基础夯实一下. 本文是参照了joy_lee的博客 闭包 在她这篇博客的基础上以批注的形式力争把我的理解阐述出 ...

  3. 【转】JS回调函数--简单易懂有实例

    JS回调函数--简单易懂有实例 初学js的时候,被回调函数搞得很晕,现在回过头来总结一下什么是回调函数. 我们先来看看回调的英文定义:A callback is a function that is ...

  4. java生成RSA公私钥字符串,简单易懂

    java生成RSA公私钥字符串,简单易懂   解决方法: 1.下载bcprov-jdk16-140.jar包,参考:http://www.yayihouse.com/yayishuwu/chapter ...

  5. HashSet的实现原理,简单易懂

    HashSet的实现原理,简单易懂   答: HashSet实际上是一个HashMap实例,都是一个存放链表的数组.它不保证存储元素的迭代顺序:此类允许使用null元素.HashSet中不允许有重复元 ...

  6. Linux服务器评测脚本 中文IO脚本简单易懂

    中文版: wget -N --no-check-certificate https://raw.githubusercontent.com/FunctionClub/ZBench/master/ZBe ...

  7. MEF入门之不求甚解,但力求简单能讲明白(四)

    上一篇我们已经可以获取各种FileHandler的实例和对应的元数据.本篇,我们做一个稍微完整的文件管理器. 1.修改接口IFileHandler,传入文件名 namespace IPart { pu ...

  8. 简单易懂, JUnit 框架问答

    本文算是一个关于Junit4相关的知识分享,但是不同于网上大段的源码分析,模式学习文章,我想通过问答的形式,引出代码来简明阐述JUnit4是如何实现需要的功能的. 考虑到任何一个框架,都是为了解决问题 ...

  9. Http与协议TCP协议简单易懂

    于C#编写代码,很多时候会遇到Http协议或TCP合约,这里做一个简单的了解. TCP对应于该传送层协议,和HTTP对应于应用层协议,从本质上讲,两者是没有可比性.Http该协议是基于TCP之上的,当 ...

随机推荐

  1. (6)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Boot项目详细搭建步骤

    ​ 在 Spring Tools 4 for Eclipse 中依次选择 File->New->Maven Project,然后在出现的界面中按图所示增加相关信息. ​ <paren ...

  2. 有关类朋友圈设计(3) -- 数据库设计&现有技术&流程设计

    在写之前,先说说当前的系统架构吧 spring cloud + zuul + eureka + oauth2 + redis + rabbitMq 这个系统是由我搭建的,当时采用的springClou ...

  3. WebView(网页视图)基本用法

    资料来源于菜鸟教程 啊这官方文档居然失效了,打不开.那我们直接就看相关方法: WebChromeClient:辅助WebView处理Javascript的对话框.网站图标.网站title.加载进度等! ...

  4. ESP8266- ESP01之AT固件下载及其他问题

    注意: 本文基于淘宝上买的安信可原装ESP-01,文章中出现的问题在另一片ESP-01S上均未出现.由于在刷固件前没有进行完整测试,因此无法判断是固件导致的还是版本不同造成的. 问题: 1.发热严重. ...

  5. C# lambda 实现 Ascii 排序

    var dir = new Dictionary<string, string>();            dir.Add("channelId", "1& ...

  6. 我在学习Blazor当中踩的巨坑!Blazor WebAssembly调试

    最近嘛,看看Blazor已经蛮成熟的.顺便想在自家的框架里使用这个东西,毕竟我还是很念旧的,而且Blazor的技术栈也不麻烦.然后呢,在调试这一关我可是踩了大坑. 我的VS是2019,很早以前装的.然 ...

  7. P3335-[ZJOI2013]蚂蚁寻路【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3335 题目大意 给出\(n\times m\)的网格,每个格子有权值.一个回路在格子的边上,要求有\(2\tim ...

  8. dbus中的数据类型

    DBus中也是类似于静态语言,使用了"强类型"数据格式.在DBus上传递的所有数据都需要声明其对应的类型,下面整理了下,DBus中的数据类型,以及在DBus中声明的数据类型是什么意 ...

  9. 92仿<高频彩>源码带采集

    需要的联系QQ 肆伍以柒柒九八一

  10. Java实现完数

    完数 找出1-1000以下的完数 public static void main(String[] args) { for(int i=2;i<1000;i++) { int sum=0; fo ...