[TOC]
IO流的本质
本地设备和不同设备之间数据的传输
IO流的分类
按照数据类型分类
字节流: 一般针对二进制文件 【视频,音频,图片】
字符流: 一般针对文本文件 【xml,json,html,txt.md...】
按照流向分
输入流: 从外界到内存
输出流: 从内存到外界
综合分类
字节流
字节输入流 InputStream
字节输出流 OutputStream
字符流
字符输入流 Reader
字符输出流 Writer
流的操作的三要素:
1.数据源: 数据需要从哪里到内存?
2.目的地: 数据从内存到哪里去?
3.交通工具:
a.弄明白到底需要输入流还是输出流,也有可能两个都需要
b.根据确定的流向在IO流框架中选取自己认为最适合的流
编码: 字符/字符数组/字符串 --> 二进制
解码: 二进制 --> 字符/字符数组/字符串
编码表: 将字符转换成对应数字的一张对照表
编码处理
编码的处理:
1.字符
2.字符串
getBytes("UTF-8");
new String(bys, "UTF-8")
3.文本文件 流
OutputStreamWriter(转换流,是字符流通向字节流的桥梁,可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认字符集编码。)
构造方法
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的字符输出转换流
OutputStreamWriter(OutputStream out, Charset cs) 创建使用cs字符集的字符输出转换流
OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用enc字符集编码器的
OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的
IO流框架
IO流框架总结
普通IO / NIO
字节流
字节流
字节流是万能流,但是在处理字符方面有时候不太方便,一般用来处理二进制文件
字节输入流
--InputStream
int available() 返回流中可用的字节数
void close() 关闭此输出流并释放与此流有关的所有系统资源。
int read() 读取一个字节
int read(byte[] b) 读取一个字节数组
int read(byte[] b, int off, int len) 读取字节数组的一部分
long skip(long n) 跳过多n个字节读取
--FileInputStream
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(FileDescriptor fdObj)
通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
-- BufferedInputStream
能够提高读写效率
注意:
1.作为输出流,文件可以不存在,会自动创建,作为输入流,文件必须存在
2.处理中文的时候不方便
字节输出流
--OutputStream
void close() 关闭此输出流并释放与此流有关的所有系统资源。
void flush() 将数据从内存中刷新到文件系统中
void write(byte[] b) 写一个字节数组
void write(byte[] b, int off, int len) 写一个字节数组的一部分
abstract void write(int b) 写一个字节
1.针对字节流可以不使用flush,针对字符流必须flush,建议都要flush
2.close释放流的资源,同时自带flush
--FileOutputStream
FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(FileDescriptor fdObj)
创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。
--BufferedOutputStream
能够提高读写效率
注意:
在不同的操作系统中对换行符的支持不一样
Windows \r\n
Linux \n
Mac \r
1.字节流在处理换行符的方面不方便
2.带append参数的表示追加写入
字符流
字符流
字符输入流
Reader
...方法与字节输入流一致
转换流: InputStreamReader
1.处理编码
2.将字节流转化成字符流
FileReader是InputStreamReader子类,用来读取字符文件的便捷类
高效缓冲字符输入流 BufferedReader
readLine() 读取一行
字符输出流
Writer
...方法与字节输出流一致
转换流: OutputStreamWriter
1.处理编码
2.将字节流转化成字符流
FileWriter是OutputStreamWriter子类,用来写入字符文件的便捷类
高效缓冲字符输出流 BufferedWriter
newLine() 写一个换行符
文件拷贝方式
文件拷贝的方式和原理:
1.FileInputStream/FileOutputStream一次性读取一个字节
2.FileInputStream/FileOutputStream一次性读取一个字节数组
3.BufferedInputStream/BufferedOutputStream一次性读取一个字节
4.BufferedInputStream/BufferedOutputStream一次性读取一个字节数组
5.FileReader/FileWriter一次性读取一个字符
6.FileReader/FileWriter一次性读取一个字符数组
7.BufferedReader/BufferedWriter一次性读取一个字符
8.BufferedReader/BufferedWriter一次性读取一个字符数组
9.BufferedReader/BufferedWriter一次性读取一行
至少有九种方式拷贝文件
使用字节流实现文件拷贝
通过这里我们需要了解计算机是如何处理中文的?
首先读取一个字节,如果人为没有转换
那么系统会根据当前的编码表来处理中文 [中文的第一个数一般是负数]
如果是正数,直接转换成对应码表的字符
如果是负数
判断编码表,假设是GBK,会等待下一个字节一起转换成对应的字符
如果是UTF-8,就会等待下两个字节一起转换成对应的字符
乱码原因:
1.人为转换
2.服务器和客户端编码表不一致
3.服务器系统编码和人为编码不一致
4.URL编码和人为解码不一致
异常
java.io.FileNotFoundException
产生原因:
1.文件盘符不存在
2.文件路径父目录不存在
java.io.IOException: Stream Closed
产生原因:
1.文件流已经关闭还在继续使用