>最近有个账单加解密的需求,正好用到 IO 流,借此机会复习一下这方面的知识,巩固记忆。
参考:
1、https://mp.weixin.qq.com/s/B55s7a2fWmEEs4BAiRPmvA
2、https://www.cnblogs.com/shuaiguoguo/p/8883862.html
3、http://hollischuang.gitee.io/tobetopjavaer/#/basics/java-basic/byte-stream-vs-character-stream
## 一、IO 的分类
IO:Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中。
IO的分类如下:

还可以根据操作对象来进行分类

主要的IO流:


## 二、字节流
操作byte类型数据,主要操作类是OutputStream、InputStream的子类;不用缓冲区,直接对文件本身操作。
### InputStream
InputStream 是一个定义了 Java 流式字节输入模式的抽象类。该类的所有方法在出错条件下引发一个IOException 异常。
常用方法:
```
// 从输入流中读取数据的下一个字节
abstract int read()
// 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中
int read(byte[] b)
// 将输入流中最多 len 个数据字节读入 byte 数组
int read(byte[] b, int off, int len)
// 跳过和丢弃此输入流中数据的 n个字节
long skip(long n)
// 关闭此输入流并释放与该流关联的所有系统资源
void close()
// 返回可以读取字节的数量
int available()
```
### OutputStream
OutputStream 是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void 值并且在出错情况下引发一个IOException异常。
常用方法:
```
// 将 b.length 个字节从指定的 byte 数组写入此输出流
void write(byte[] b)
// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
void write(byte[] b, int off, int len)
// 将指定的字节写入此输出流
abstract void write(int b)
// 关闭此输出流并释放与此流有关的所有系统资源
void close()
// 刷新此输出流并强制写出所有缓冲的输出字节
void flush()
```
## 三、字符流
操作字符类型数据,主要操作类是Reader、Writer的子类;使用缓冲区缓冲字符,不关闭流就不会输出任何内容。
### Reader
Reader 是 Java 定义的流式字符输入模式的抽象类。类中的方法在出错时引发 IOException 异常。
常用方法:
```
// 读取单个字符
int read()
// 将字符读入数组
int read(char[] cbuf)
// 将字符读入数组的某一部分
abstract int read(char[] cbuf, int off, int len)
// 跳过字符
long skip(long n)
// 关闭该流并释放与之关联的所有资源
abstract void close()
```
### Writer
Writer 是定义流式字符输出的抽象类。所有该类的方法都返回一个 void 值并在出错条件下引发 IOException 异常。
常用方法:
```
// 写入字符数组
void write(char[] cbuf)
// 写入字符数组的某一部分
abstract void write(char[] cbuf, int off, int len)
// 写入单个字符
void write(int c)
// 写入字符串
void write(String str)
// 写入字符串的某一部分
void write(String str, int off, int len)
// 将指定字符添加到此 writer
Writer append(char c)
// 将指定字符序列添加到此 writer
Writer append(CharSequence csq)
// 将指定字符序列的子序列添加到此 writer.Appendable
Writer append(CharSequence csq, int start, int end)
// 关闭此流,但要先刷新它
abstract void close()
// 刷新该流的缓冲
abstract void flush()
```
## 四、字节流与字符流相互转换
整个IO包实际上分为字节流和字符流,但是除了这两个流之外,还存在一组字节流-字符流的转换类。
OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流输出对象。
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象。
## 五、outputStream 与 inputStream 的相互转换
有时会需要将 outputStream 与 inputStream 进行相互转换,记录一下转换的方法。
### inputStream 转 outputStream
```
public ByteArrayOutputStream parse(InputStream in) throws Exception
{
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
int ch;
while ((ch = in.read()) != -1) {
swapStream.write(ch);
}
return swapStream;
}
```
### outputStream 转 inputStream
```
public ByteArrayInputStream parse(OutputStream out) throws Exception
{
ByteArrayOutputStream baos=new ByteArrayOutputStream();
baos=(ByteArrayOutputStream) out;
ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
return swapStream;
}
```
### inputStream 转 String
```
public String parse_String(InputStream in) throws Exception
{
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
int ch;
while ((ch = in.read()) != -1) {
swapStream.write(ch);
}
return swapStream.toString();
}
```
### OutputStream 转 String
```
public String parse_String(OutputStream out)throws Exception
{
ByteArrayOutputStream baos=new ByteArrayOutputStream();
baos=(ByteArrayOutputStream) out;
ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
return swapStream.toString();
}
```
### String 转 inputStream
```
public ByteArrayInputStream parse_inputStream(String in)throws Exception
{
ByteArrayInputStream input=new ByteArrayInputStream(in.getBytes());
return input;
}
```
### String 转 outputStream
```
public ByteArrayOutputStream parse_outputStream(String in)throws Exception
{
return parse(parse_inputStream(in));
}
```

Java IO流