一、I/O系统的分类
1.输入流:程序从输入流读取数据
输出流:程序向输出流写入数据
2.字节流:数据流中的最小的数据单元是字节
字符流:数据流中的最小单元是字符
3.节点流、处理流
二、I/O系统的四个抽象类
1.Java中提供的流类型在包java.io内,分别继承自四个抽象类
2.I/O系统的四个抽象类
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
如果是多媒体文件我们使用字节流,因为字符流会破坏对媒体文件,而word文档这种文件还是主要使用的是字符流,因为中文不乱码
public class FileInputStreamTest {
public static void main(String[] args) {
//我们使用的是字节流,而一个汉字等于一个字符,一个字符等于两个字节,而读取输出的时候会将
//汉字拆开,所以控制台显示的时候时中文乱码,而往文件中写入的时候,由于文件不会打开,所以会将汉字的
//两个字节组合为汉字,所以文件中中文不会乱码
//文件输入字节流
FileInputStream fis = null;
//文件输出字节流
FileOutputStream fos = null;
try{//相对路径是从src开始的
fis = new FileInputStream
("src/com/haina365/lesson18/9..jpg");
// ("src/main/java/com/haina365/lesson18/FileStreamTest.java");
//如果输出的文件已经存在则直接写入,如果不存在,则新建文件在保存内容中
fos = new FileOutputStream
("src/com/haina365/lesson18/9.jpg");
// ("src/com/haina365/lesson18/text.txt");
int a = 0;
//read读取文件中的数据,都是大于0的数,当返回结构为-1时,表示读取结束
while((a = fis.read()) != -1){
fos.write(a);//将内存中的数据写入到文件
System.out.print((char) a);
}
}catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
public class FileReaderTest {
public static void main(String[] args) {
//文件输入字符流
FileReader fr = null;
//文件输入字符流
FileWriter fw = null;
try{
fr = new FileReader
("src/com/haina365/lesson18/9.jpg");
//("src/main/java/com/haina365/lesson18/FileStreamTest.java");
fw = new FileWriter
("src/com/haina365/lesson18/1..jpg");
// ("src/com/haina365/lesson18/demo.txt");
int a = 0;
while((a = fr.read()) != -1){
fw.write(a);
System.out.print((char)a);
}
fw.flush();//保存
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
}
三、节点流
节点流分类:
类型 | 字节流 | 字符流 |
文件 | FileInputStream FileOutputStream | FileReader FileWriter |
数组 | ByteArrayInputStream ByteArrayOutputStream | CharArrayReader CharArrayWriter |
字符串 | StringReader StringWriter | |
管道 | PipedInputStream PipedOutputStream | PipedReader PipedWriter |
四、文件流
1.FileInputStream类:从文件系统中的某个文件中获得输入字节
常用方法:
(1)int read()
(2)long skip(long n)
(3)void close()
2.FileOutputStream类:用于将数据写入文件的输出流
常用方法:
(1)void write(int b)
(2)void close()
3.FileReader类与FileWriter类为增加其它方法
五、装饰器模式
1.目的:解决过度依赖继承,难以用创建类的方式来进行对象的功能扩展的问题
2.实现方式:用对象数量换类的数量
3.应用场景:
(1)扩展一个类的功能,给一个类增加附加责任
(2)不单一依赖继承,增加由一些基本的排列组合产生大量的功能(需要创建很多功能类)
(3)对目标进行选择扩展,动态增加功能且可以动态撤销
4.优点:虽然装饰模式产生的初衷是装饰器类对默认目标实现类的行为扩展,装饰器类却并不对默认目标实现类形成依赖
5.缺点:增加了对象
(1)共同的父类(接口),导致创建的对象类似,给查错带来困难
(2)对象的创建增加了空间的开销
六、处理流
处理流分类
类型 | 字节流 | 字符流 |
过滤器(装饰器) | FileInputStream FileOutputStream | FileReader(抽象类) FileWriter(抽象类) |
缓冲流 | BufferedInputStream BufferedOutputStream | BufferedReader BufferedWriter |
转换流 | InputStreamReader OutputStreamReader | |
数据流 | DataInputStream DataOutputStream | |
对象流 | ObjectInputStream ObjectOutputStream | |
打印流 | PrintStream | PrintWriter |
七、缓冲流
1.BufferedInputStream类:创建一个内部缓冲区数组,默认为defaultBufferSize=8192相当于8k
(1)套接InputStream类型流
(2)常用方法:
void mark(int readlimit)
void reset()
2.BufferedOutputStream类:实现缓冲的输出流,应用程序就可以一次将多个字节写入文件系统
(1)套接OutputStream类型流
(2)常用方法:
void flush()
3.BufferedReader类
套接Reader类型流,常用方法同BufferedInputStream类
String readLine()
4.BufferedWriter类
套接Writer类型流,常用方法同BufferedOutputStream类
void newLine()
public class BufferedInputStreamTest {
//处理流要想正常必须要有节点流,因为节点流是真正具有输入输出功能的流,而
//处理流只能增强输入输出功能,但是没有输入输出功能
public static void main(String[] args) {
//文件输入字节流
FileInputStream fis = null;
//缓冲输入字节流
BufferedInputStream bis = null;
//输入转换流
InputStreamReader isr = null;
//文件输入字节流
FileOutputStream fos =null;
//文件输出字节流
BufferedOutputStream bos = null;
//输出转换流
OutputStreamWriter osw = null;
try{
fis = new FileInputStream
("src/com/haina365/lesson19/BufferedInputStreamTest.java");
//缓冲区底层是一个数组,大小为8k
bis = new BufferedInputStream(fis);
//处理流在使用的时候,谁先用谁后用没有顺序,可以随意使用
//gbk utf-8 gb2312支持中文的编码集
isr = new InputStreamReader(bis,"gbk");
//在输出流的第二个参数上写true,就修改保存文档中的形式由覆盖变成了追加
fos = new FileOutputStream("src/com/haina365/lesson19/text.txt",true);
bos = new BufferedOutputStream(fos);
osw = new OutputStreamWriter(bos,"gbk");
int a =0;
//注意有处理流后,用什么方式读数据,就用什么方式写数据
while((a = isr.read()) != -1){
osw.write(a);
System.out.print((char)a);
}
osw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
八、转换流
1.InputStreamReader类:它使用指定的字符集读取字节并将其解码为字符
套接InputStream类型流
2.OutputStreamReader类:可使用指定的字符集将要写入流中的字符编码
套接OutputStream类型流
3.常用方法:String getEncoding()
九、数据流
1.DataInputStream类:允许应用程序以与机器无关方式从底层输入流中读取基本Java数据类型
(1)套接InputStream类型流
(2)常用方法:数据类型 read数据类型()
2.DataOutputStream类:应用程序以适当方式将基本Java数据类型写入输出流中
(1)套接OutputStream类型流
(2)常用方法:数据类型 write数据类型()
十、打印流
1.打印流:属于输出流,方便地打印各种数据值的表示形式
(1)提供了print()、println()方法的多种重载形式
(2)不会抛出异常,用户通过检测错误状态获取错误信息
(3)有自动刷新功能,自动调用flush()方法
(4)套接OutputStream类型流
2.PrintStream类:针对字节操作的输出流
打印字符时适用平台默认字符编码
3.PrintWriter类:针对字符操作的输出流
十一、对象流
1.java.io.Serializable接口:实现此接口启用其序列化功能
2.transient关键字:用此关键字修饰的成员变量不被序列化
3.ObjectInputStream类:可以为应用程序提供对对象图形的持久存储,对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化
(1)套接InputStream类型流
(2)常用方法:
int available()
int skipBytes(int len)
public class ObjectInputStreamTest {
public static void main(String[] args) {
FileInputStream fis = null;//文件输入流
ObjectInputStream ois = null;//文件输出流
try {
fis = new FileInputStream("src/com/haina365/lesson19/Student.txt");
ois = new ObjectInputStream(fis);
//读取文件中的对象,一次获取一个对象,同时读取到的对象都是Object类型的
Student s1 = (Student) ois.readObject();
System.out.println(s1);
Student s2 = (Student) ois.readObject();
System.out.println(s2);
Student s3 = (Student) ois.readObject();
System.out.println(s3);
Student s4 = (Student) ois.readObject();
System.out.println(s4);
//以EOFEException异常作为文件读取结束的标志
} catch (EOFException e) {
System.out.println("文件读取结束");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
//先关闭最外层的处理流再关里面的节点流
if (ois != null) {
ois.close();
}
//如果代码中既有输入流还有输出流,那么关闭的时候输入输出流谁先可以谁会都可以
if (fis != null) {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
4.ObjectOutputStream类:将Java对象的基本数据类型和图形写入OutputStream,只能将支持java.io.Serializable接口的对象写入流中
套接OutputStream类型流
public class ObjectOutputStreamTest {
public static void main(String[] args) {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream
("src/com/haina365/lesson19/Student.txt");
oos = new ObjectOutputStream(fos);
Student s1 = new Student(1001,"张三",18);
Student s2 = new Student(1001,"张三",18);
Student s3 = new Student(1001,"张三",18);
oos.writeObject(s1);//往文件中写入对象的写法
oos.writeObject(s2);
oos.writeObject(s3);
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.使用对象流要先开启对象的序列化功能,开启方式是类实现序列化接口(Serializable)
瞬时状态:保存在内存中的数据,其状态为瞬时状态
持久状态:保存在硬盘中的数据,其状态为持久状态
序列化:数据有瞬时状态变成持久状态就是序列化
反序列化:数据由持久化状态变为瞬时状态就是反序列化。
public class Student implements Serializable {
private int no;
private String name;
private int age;
public Student(int no,String name,int age){
this.no = no;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}