上次一个同事突然问了我java文件的读取,我的第一反应就是去网上找,虽然也能找到,但自己总感觉不是很踏实,所以今晚就抽空总结些关于java IO流的资料,为以后的使用提供方便.......
(1).流的定义:
是一种数据操作模型: 把任何数据都作为Byte的有序集合看待,逐一处理的方式方式叫做流 。
流的分类: 字节流 和字符流(按流数据的格式来划分),可以看下图,IO流对象的继承关系和作用
字节流
InputStream 最基本的输入流操作模型, 是抽象类(read()是没有实现的)
|-- FileInputStream 实现了在文件上读取的方法 read(), 节点流
|-- ByteArrayInputStream 实现了在数组里读取的方法 read()
|-- FilterInputStream 过滤流,包装在一个基本流外部,提供功能扩展
| |-- DataInputStream 为基本流扩展了基本数据类型读取
| | readInt() readDouble()...方法的底层是read()
| |-- BufferedInputStream 为基本流提供缓冲处理
| |-- CipherInputStream 解密输入流, 知道就行
| |-- ZipInputStream 解压输入流, 知道就行
|-- ObjectInputStream 对象输入流, 也是过滤器
OutputStream 最基本的输出流操作模型,是抽象类(write()是没有实现的)
|-- FileOutputStream 实现了在文件上写出的方法 write(), 节点流
|-- ByteArrayOutputStream 在变长数组上实现了write() 方法
|-- FilterOutputStream
| |-- DataOutputStream 基本类型输出
| |
| |-- BufferedOutputStream 缓冲输出
| |-- CipherOutputStream 加密输出
| |-- ZipOutputStream 压缩输出
|-- ObjectOutputStream 对象输出流
字符流
Reader 抽象类, 定义了抽象方法read(), 每次读取一个字符
|-- InputStreamReader 也是过滤器, 将byte序列解码为char序列
| 底层也是依赖基本的byte输入流
|-- BufferedReader (Scanner) 是字符流过滤器,
| 有常用的文本读取方法readLine()
|-- FileReader 底层是 FileInputSream + InputStreamReader
| 不能指定读取文件的字符编码
Writer 抽象类, 定义抽象方法write() 每次写出一个字符
|-- OutputStreamWriter 也是过滤器, 将char序列编码为byte序列
| 底层也是依赖基本的byte输出流
|-- PrintWriter 是过滤器, 提供了常用方法println()
| 非常常见的文本处理方法
|-- FileWriter = OutputStreamWriter + FileOutputStream
| 不能指定文本输出编码, 不好用!
下面写了几个小例子 来说明字节流 和字符流的操作
package test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
/**
*
* @author leo
*
*/
public class IODemo {
/**
* 单字节读取文件
* @param fileName
*/
public void readFromFileByByte(String fileName){
File file = new File(fileName);
//输入流
try {
FileInputStream in = new FileInputStream(file);
int temp;
while((temp =in.read())!=-1){
System.out.print(temp);
}
//关闭流
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 按单字符来读取文件
* @param fileName
*/
public void readFromFileByReader(String filePath){
try {
Reader in = new InputStreamReader(new FileInputStream(new File(filePath)), "UTF-8");
int temp;
while((temp =in.read())!=-1){
if(((char)temp)=='\r'){
System.out.print((char)temp);
}
}
//关闭流
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 复制文件(只能复制文件! 不支持文件夹的复制!)
* @param src 源文件
* @param dsc 目标文件
*/
public void copyFile(String src,String dsc){
File file = new File(src);
//输入流
try {
FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(new File(dsc));
//使用多字节读取
byte[] buf = new byte[10*1024];
int temp;
while((temp =in.read(buf))!=-1){
out.write(buf, 0, temp);
}
//关闭流
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 复制文件 按行来读取(只能复制文件! 不支持文件夹的复制!)
* @param src 源文件
* @param dsc 目标文件
*/
public void copyFileByReadLine(String src,String dsc){
File file = new File(src);
//输入流
try {
BufferedReader in = new BufferedReader(new FileReader(file)) ;
BufferedWriter out = new BufferedWriter(new FileWriter(new File(dsc)));
String temp;
//按行读取
while((temp =in.readLine())!=null){
//写入一行
out.append(temp);
//换行
out.newLine();
//清掉流的缓冲区,避免文件过大
out.flush();
}
//关闭流
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2).序列化 和反序列化
序列化:将对象转化成流的过程称为序列化
反序列化:将流转化成对象的过程称之为反序列化
序列化与反序列化必须遵守的原则: 必须实现Serializable接口
下面有个demo 是我在项目中通过序列化 和反序列化来实现对象的deepCopy(深层复制):
package test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 序列化 和反序列化
* @author leo
*
*/
public class IODemo2 implements Serializable{
/**
* 通过 序列化 和反序列化 实现深层复制对象
* @param obj
* @return
*/
public static Object deepCopy(Object obj) {
try {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(buf);
oos.writeObject(obj);// 将对象序列化到byte数组流中
oos.close();
//将数组流 转换数组
byte[] ary = buf.toByteArray();
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(ary));
Object o = ois.readObject();// 从byte数组流中反序列化对象
ois.close();
return o;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}