缓冲流、转换流、序列化流
第一章 缓冲流
昨天学习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流。比如能够高效读写的缓冲流,能够 转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上 创建而来的,就像穿上铠甲的武士一样,相当于是对基本流对象的一种增强。
缓冲字节输入流
BufferedInputStream
package com.hqyj.demo07;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
java.io.InputStream
java.io.FilterInputStream
java.io.BufferedInputStream
java.io.InputStream
此类是一个抽象类,表示输入字节流的所有类的超类
定义一些子类共性的成员方法:
public abstract int read()throws IOException从输入流读取数据的下一个字节。
public int read(byte[] b)throws IOException从输入流读取一些字节数,并将它们存储到缓冲区b 。
public int read(byte[] b,int off,int len)throws IOException从输入流读取len字节的数据到一个字节数组。
java.io.BufferedInputStream
构造方法:
public BufferedInputStream(InputStream in)
创建一个BufferedInputStream并保存其参数,输入流in供以后使用。
public BufferedInputStream(InputStream in,int size)
创建具有BufferedInputStream缓冲区大小的BufferedInputStream,并保存其参数,输入流in供以后使用。
*/
public class BufferedInputStreamTest01 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
/*int len = 0;//字节
while ((len=bis.read())!=-1){
System.out.println(len);
}*/
byte[] bytes = new byte[1024];//字节
int len = 0;//有效字节数
while ((len=bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
fis.close();
bis.close();
}
}
缓冲字节输出流
BufferedOutputStream
package com.hqyj.demo07;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
java.io.OutputStream
java.io.FilterOutputStream
java.io.BufferedOutputStream
此类是一个抽象类,表示输出字节流的所有类的超类
定义一些子类共性的成员方法:
public void close()throws IOException关闭此输出流并释放与此流相关联的任何系统资源
public void flush()throws IOException刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b)throws IOException将b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b,int off,int len)throws IOException从指定的字节数组写入len字节,从偏移off开始输出到此输出流。
public abstract void write(int b)throws IOException将指定的字节写入此输出流。
java.io.BufferedOutputStream
构造方法:
public BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
public BufferedOutputStream(OutputStream out,int size)
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
*/
public class BufferedOutputStreamTest01 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("a.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("我把数据写在内部缓冲区".getBytes());
bos.flush();
bos.close();
}
}
缓冲字符输入流
BufferedReader
特有的方法:
public String readLine() throws IOException读一行文字。
package com.hqyj.demo07;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
java.io.Reader
java.io.BufferedReader
定义一些子类共性的成员方法:
public int read()throws IOException
spublic int read(char[] cbuf)throws IOException将字符读入数组。
java.io.BufferedReader
构造方法:
public BufferedReader(Reader in)创建使用默认大小的输入缓冲区的缓冲字符输入流。
public BufferedReader(Reader in,int sz)创建使用指定大小的输入缓冲区的缓冲字符输入流。
特有的方法:
public String readLine()throws IOException读一行文字。
*/
public class BufferedReaderTest01 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
字符缓冲输出流
BufferedWriter
特有的方法:
public void newLine() throws IOException写一行,行分隔符
package com.hqyj.wy.Demo1;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*
java.io.Writer
java.io.BufferedWriter
定义一些子类共性的成员方法:
public void write(int c) throws IOException写一个字符
public void write(char[] cbuf) throws IOException写入一个字符数组。
public abstract void write(char[] cbuf,int off,int len) throws IOException写入字符数组的一部分。
public void write(String str)throws IOException写一个字符串
public void write(String str,int off,int len)throws IOException写一个字符串的一部分。
public abstract void flush()throws IOException刷新流。
public abstract void close()throws IOException关闭流,先刷新
java.io.BufferedWriter
构造方法:
public BufferedWriter(Writer out)创建使用默认大小的输出缓冲区的缓冲字符输出流。
public BufferedWriter(Writer out,int sz)创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
特有的方法:
public void newLine()throws IOException写一行,行分隔符。
*/
public class BufferedWriterTest01 {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
for (int i = 0; i < 10; i++) {
bw.write("你好,JAVA");
bw.newLine();//换行 == \r \n
}
bw.close();
}
}
缓冲字节输入输出流效率高
package com.hqyj.demo07;
/*
缓冲字节输入输出流效率高:
图片文件复制:一边读一边写
数据源:d:\\2.jpg
数据的目的地:e:\\2.jpg
文件复制的步骤:
1.创建一个缓冲字节输入流对象,构造方法中要绑定要读取的数据源
2.创建一个缓冲字节输出流对象,构造方法中要绑定要写入的数据的目的地
3.使用read()和write()方法,一边读一边写
4.释放资源
复制文件共消耗:3毫秒
*/
import java.io.*;
public class FileCopy02 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\1.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\1.jpg"));
int len = 0;
byte[] bytes = new byte[1024];
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
long end = System.currentTimeMillis();
System.out.println("共耗时:"+(end-start)+"毫秒");
}
}
2.2编码引出的问题
转换流
package com.hqyj.demo08;
import java.io.FileReader;
import java.io.IOException;
/*
FileReader可以读取IDEA默认编码格式(UTF-8)
FileReader可以读取系统默认编码(中文GBK)格式会产生乱码����
*/
public class FileReaderTest {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("我是GBK文件.txt");
int len = 0;
while ((len=fr.read())!=-1){
System.out.println((char)len);
}
fr.close();
}
package com.hqyj.demo08;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/*
java.io.Reader
java.io.InputStreamReader
public InputStreamReader(InputStream in,String charsetName)throws UnsupportedEncodingException
创建一个使用命名字符集的InputStreamReader。
*/
public class InputStreamReaderTest {
public static void main(String[] args) throws IOException {
read_utf_8();
}
//读取utf-8编码的文件
private static void read_utf_8() throws IOException {
InputStreamReader isr = new InputStreamReader(newFileInputStream("utf_8.txt"),"utf-8");
int len = 0;
while ((len=isr.read())!=-1){
System.out.println((char)len);
}
isr.close();
}
}
package com.hqyj.demo08;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
java.io.Writer
java.io.OutputStreamWriter
public OutputStreamWriter(OutputStream out,
String charsetName)
throws UnsupportedEncodingException创建一个使用命名字符集的OutputStreamWriter。
设置编码的时候,参数不区分大小写 GBK/gbk;UTF-8/utf-8
不指定编码默认用UTF-8
*/
public class OutputStreamWriterTest {
public static void main(String[] args) throws IOException {
write_gbk();
}
//写入GBK编码文件
private static void write_gbk() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
osw.write("你好鸭");
osw.flush();
osw.close();
}
}
序列化
ObjectOutputStream类
package com.hqyj.demo09;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/*
序列化:将对象写入到文件中
java.io.OutputStream
java.io.ObjectOutputStream
构造方法:
public ObjectOutputStream(OutputStream out)
throws IOException
特定方法:
public final void writeObject(Object obj)
throws IOException
*/
public class ObjectOutputStreamTest {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
oos.writeObject(new Person("易烊千玺",21));
oos.close();
}
}
反序列化:将对象从文件中读取出来
package com.hqyj.demo09;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
反序列化:将对象从文件中读取出来
java.io.InputStream
java.io.ObjectInputStream
构造方法:
public ObjectInputStream(InputStream in)
throws IOException创建从指定的InputStream读取的ObjectInputStream。
特定方法:
public final Object readObject()
throws IOException,
ClassNotFoundException
异常:没序列化异常
Exception in thread "main" java.io.NotSerializableException: com.hqyj.demo09.Person
前提:
Person类要实现Serializable接口(序列化接口-标记型接口),启动序列化功能,不实现会报以上异常
*/
public class ObjectInputStreamTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));
Object o = ois.readObject();
Person p =(Person)o;
System.out.println(p.getName()+"-"+p.getAge());
ois.close();
}
}
package com.hqyj.demo09;
import java.io.Serializable;
/**
* 不添加序列化版本号,会报以下异常:
* 表明Person类在改动前后生成了两个序列化版本号,不一致导致无法反序列化
* java.io.InvalidClassException:
* com.hqyj.demo09.Person; local class incompatible:
* stream classdesc serialVersionUID = 842344862260111050,
* local class serialVersionUID = -4421721788509217275
*
* 不被序列化的两个关键字:
*transient static
*/
public class Person implements Serializable {
private static final long serialVersionUID = -2782143034241084058L;
//序列化版本号
//private static final long serialVersionUID = 12L;
private String name;
private int age;
//private transient int age;//不被序列化
//private static int age;//不被序列化
private String hobby;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
打印流
package com.hqyj.demo10;
import java.io.FileNotFoundException;
import java.io.PrintStream;
/*
java.io.OutputStream
java.io.FilterOutputStream
java.io.PrintStream
特点:
1.只负责数据的输出,不负责数据的读取
2.与其他流不同,它不会抛出IOException
3.特有的方法:print(),println()
注意:
使用继承自父类中的write方法,那么它查看数据的时候会自动查看编码表,97-a
使用自己特有的print(),println()方法,它写入的数据会原样写入,97-97
*/
public class PrintStreamTest01 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("print.txt");
ps.write(97);
ps.println(97);
ps.println(true);
ps.print("abc");
ps.close();
}
}
package com.hqyj.demo10;
import java.io.FileNotFoundException;
import java.io.PrintStream;
/*
改变输出流的目的地(打印流的语句)
输出语句默认打印到控制台
使用System.setOut可以改变输出语句的目的地,改为参数中传递的打印流的目的地
public static void setOut(PrintStream out)重新分配“标准”输出流。
*/
public class PrintStreamTest02 {
public static void main(String[] args) throws FileNotFoundException {
System.out.println("我是打印到控制台的");//打印到控制台
PrintStream ps = new PrintStream("end.txt");
System.setOut(ps);
System.out.println("我是打印到end.txt的");//打印到end.txt
ps.close();
}
}