【思维导图】
【IO流分类】
根据处理数据类型的不同分为字节流
和 字符流
根据数据流向不同分为输出流
和 输入流
字节流和字符流的区别
字符流底层是字节流
字符流需要考虑编码问题 字节流不需要
字符流只能操作文本文件 字节流可以操作所有文件
字节流是直接操作文件的 字符流是通过缓存操作文件
输入流和输出流
输入流只能进行读操作,输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。
【字节输入流 InputStream】
InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)
【字节输出流 InputStream】
OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。
PipedOutputStream 是向与其它线程共用的管道中写入数据。
ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
总的来说
输入流:InputStream或者Reader:从文件中读到程序中;
输出流:OutputStream或者Writer:从程序中输出到文件中;
【字节流操作文件】
FileInputStream读取文件内容
package com.io;
import java.io.FileInputStream;
import java.io.IOException;
public static void main(String[] args){
try(
FileInputStream in = new FileInputStream("D:\\1.txt");
){
byte[] bs = new byte[1024];
int len = 0;
while((len = bis.read(bs)) != -1){
System.out.println(new String(bs,0,len));
}
}catch(IOException e){
e.printStackTrace();
}
}
FileOutputStream 实现复制文件
package com.io;
import java.io.FileInputStream;
import java.io.FileOutPutStream;
import java.io.IOException;
public static void main(String[] args){
try(
FileInputStream in = new FileInputStream("D:\\1.txt");
FileOutPutStream out = new FileOutputStream("D:\\2.txt");
){
byte[] bs = new byte[1024];
int len = 0;
while((len = in.read(bs))!=-1){
out.write(bs,0,len);
}
}catch(IOException e){
e.printStackTrace();
}
}
注: 在jdk7后,提供了一种新的方式:try-with-resources方式来管理资源,在try中声明资源,当程序执行完后,会自动将声明的资源关闭掉
【字符流实现复制文件】
package com.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
public static void main(String[] args){
try(
BufferedInputStream bis = new BufferedInputStream("D:\\1.txt");
BufferedOutputStream bos = new BufferedOutputStream("D:\\2.txt");
){
byte[] bs = new byte[1024];
int len = 0;
while((len = bis.read(bs))!=-1){
bos.write(bs,0,len);
}
}catch(IOException e){
e.printStackTrace();
}
}
【对象的序列化】
目的:将一个具体的对象进行持久化,写入到硬盘上。
注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。
如何将非静态的数据不进行序列化?用transient 关键字修饰此变量即可。
Serializable:用于启动对象的序列化功能,可以强制让指定类具备序列化功能,该接口中没有成员,这是一个标记接口。这个标记接口用于给序列化类提供UID。这个uid是依据类中的成员的数字签名进行运行获取的。如果不需要自动获取一个uid,可以在类中,手动指定一个名称为serialVersionUID id号。依据编译器的不同,或者对信息的高度敏感性。最好每一个序列化的类都进行手动显示的UID的指定。
实体类
package com.yan.entity;
import java.io.Serializable;
public class Student implements Serializable{//实现Serializable接口
/**
*
*/
private static final long serialVersionUID = 8691134767391266961L;
private String name;
private Integer age;
public Student() {
super();
}
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
测试类
package com.yan.demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.junit.Test;
import com.yan.entity.Student;
public class ObjectDemo {
@Test
public void fun1() {
try (
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Desktop\\1.txt"));
){
Student s = new Student("张三",12);
oos.writeObject(s);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void fun2() {
try (
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Desktop\\1.txt"));
){
Student s = (Student) ois.readObject();
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}