缓冲流,转换流
1.缓冲流
1.定义
缓冲流,也是高效流,是对四个基本的FileXxx流的增强. 所以也是四个流
- 字节缓冲流:
BufferedInputStream
,BufferedOutputStream
- 字符缓冲流:
BufferedReader
,BufferedWriter
缓冲流的基本原理,实在创建对象时,会创建一个内置默认大小的缓冲区数组,通过缓冲区读写,减少系统io次数
2.字节缓冲流
构造方法
public BufferedInputStream(InputStream in)
:创建一个新的缓冲流对象public BufferedOutputStream(OutputStream out)
:创建一个新的缓冲流对象
构造举例
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
使用缓冲流进行案例实现
public class BufferedDemo{
public static void main(String[] args){
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try(
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk.exe"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
){
//读写数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
}catch(IOException e){
e.printStackTrace();
}
// 记录结束的时间
long end = System.currentTImeMillis();
System.out.println("索要时间为"+(end-start)+"毫秒");
}
}
}
使用数组,加快速度
public class BufferedDemo{
public static void main(String[] args){
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try(
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk.exe"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
){
//读写数据
int len;
byte[] bytes = new byte[8*1024];
while((len=bis.read())!=-1){
bos.write(bytes, 0, len);
}catch(IOException e){
e.printStackTrace();
}
// 记录结束的时间
long end = System.currentTImeMillis();
System.out.println("索要时间为"+(end-start)+"毫秒");
}
}
}
3.字符缓冲流
构造方法
public BufferedReader(Reader in)
:创建一个新的缓冲输入流public BufferedWriter(Writer out)
:创建一个新的缓冲输出流
构造举例
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
特有方法
字符缓冲流的基本方法和普通字符流调用方式一致
BufferedReader
:public String readLine()
:读一行文字BuffferedWriter
:public void newLine()
:写一行行分隔符,有系统定义符号
readLine
方法演示
public class BufferedReaderDemo{
public static void main(String[] args) throws IOException{
//创建流对象
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
//定义字符串,保存读取的一行文字
String line = null;
//循环读取,读到最后返回null
while((line=br.read())!=null){
System.out.println(line);
System.out.println("-----");
}
//释放资源
br.close();
}
}
newLine
方法演示
public class BufferedWriterDemo{
public static void main(String[] args) throws IOException{
// 创建流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
//写出数据
bw.write("黑马");
bw.newLine();
bw.write("程序");
bw.newLine();
//释放资源
bw.close();
}
}
2.转换流
1.IuputStreamReader
类
转换流java.io/InputStreamReader
, 是Reader
的子类, 他读去字节, 并使用指定的字符集将其解码为字符.
构造方法
InputStreamReader(InputStream in)
:创建一个使用默认字符集的字符流InputStreamReader(InputStream in, String charsetName)
:创建一个指定字符集的字符流
构造举例
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"), "GBK");
指定编码读取
public class ReaderDemo{
public static void main(String[] args) throws IOException{
// 定义文件位置, 文件为gbk编码
String FileName = "E:\\file_txt";
// 创建流对象指定为GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName), "GBK");
//定义变量, 保存字符
int read;
//循环读取
while((read=isr.read())!=-1){
System.out.println((char) read);
}
//关闭资源
isr.close();
}
}
2.OutputStreamWrite
类
是Write
的子类
构造方法
OutputStreamWriter(OutputStream in)
:创建一个使用默认字符集的字符流OutputStreamWriter(OutputStream in, String chasetName)
:创建一个指定字符集的字符流
构造例子
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
指定编码写出
public class OutputDemo{
public static void main(String[] args) throws IOException{
//定义文件路径
String FileName = "E:\\out.txt";
//创建流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName), "GBK");
osw.write("你好");
osw.close();
}
}
3.序列化
Java中提供了一种对象序列化的机制,用一个字节序列可以表示一个对象,该字节序列包含该 对象的数据
、 对象的 类型
和 对象中存储的属性
等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据
、对象的类型
和对象中 存储的数据
信息,都可以用来在内存中创建对象。
1.ObjectOutputStream类
构造方法
public ObjectOutputStream(OutputStream out)
:穿件一个指定的OutputStream的ObjectOutputStream
构造例子
FileOutputStream FileOut = new FileOutputStream("a.txt");
ObjectOutputStream out = new ObjectOutputStream(FileOut);
序列化操作
1.一个对象要想序列化,必须满足两个条件
- 该类是
java.io.Serializable
接口,Serializable
是一个标记接口,不实现此接口不会使用任何状态序列化和反序列化, 会抛出NotSerializableException
- 该类的所有属性必须是可序列化的,如果有一个属性不要可序列化的, 则改属性必须是注明是瞬态的,使用
transient
关键字修饰
public class Employle implements java.io.Serializable{
public String name;
public String address;
public transient int age; //tanisent瞬态修饰成员, 不会被序列化
}
2.写出对象方法
public final void writeObject(Object obj)
:将制定的对象写出
public class Serializable{
public static void main(String[] args){
Employee e = new Employee();
e.name = "张三";
e.address = "北大";
e.age = 20;
try{
//创建序列化流对象
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("a.txt"));
//写出对象
out.writeObject(e);
//释放资源
out.close();
Fileout.close();
System.out.println("Serializable 打他 is saved")
}catch(IOException i){
i.printStackTrace();
}
}
}
2.ObjectInputStream
类
构造方法
public ObjectInputStream(InputStream in)
:穿件一个指定InputStream的ObjectInputStream.
反序列化操作1
如果可以找到一个对象的class文件,我们可以进行反序列化操作
public final Object readObject()
:读取一个对象
public class DeserialixeDemo{
public static void main(String[] args){
Employee e = null;
try{
//创建反序列化流
FileInputStream fileIn = new FileInputStream("a.txt");
ObjectInputStream in = new ObjectInputStream(FileIn);
//读取一个对象
e = (Employee) in .readObject();
//释放资源
in.close();
fileIn.close();
}catch(IOException i){
//捕获异常
i.printStackTrace();
return;
}catch(ClassNotFoundException c){
// 捕获找不到异常
System.out.println("not found");
c.printStrackTrace();
return;
}
// 无异常,直接打印输出
System.out.println(e.name);
System.out.println(e.address);
System.out.println(e.age);
}
}
反序列化操作2
另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操
作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:
- 该类的序列版本号与从流中读取的类描述符的版本号不匹配
- 该类包含未知数据类型
- 该类没有可访问的无参数构造方法
Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序 列化的对象和对应类是否版本匹配
public class Employee implements java.io.Serializable{
//加入序列版本号
private static final long serialVersionUID = 1L;
public String name;
public String address;
//添加新的属性,重新编译
public int eid;
public void adressCheck(){
System.out.println("adress check"+name+"--"+adress);
}
}
4.打印流
平时我们使用控制台打印,print和println
来自于java.io.PrintStream
类
1.PrintStream类
构造方法
public PrintStream(String FileName)
:使用指定的文件名创建一个新的打印流
构造例子
PrintStream ps = new PrintStream("ps.txt");
改变打印流向
System.out
就是PrintStream
类型的
public class PrintDemo{
public static void main(String[] args) throws IOException{
//调用系统的打印流
System.out.println(97);
//创建打印流,指定文件的名称
PrintStream ps = new PrintStream("ps.txt");
// 设置系统的流向到ps.txt中
System.setOut(ps);
//调用打印的方法, ps.txt中输出97
System.out.println(97);
}
}