文章目录
缓冲流、转换流、序列化流、打印流
一、缓冲流
1. 缓冲流的原理
2. BufferedOutputStream字节缓冲输出流
java.io.BufferedOutputStream extends OutputStream
BufferedOutputStream
字节缓冲输出流。- 继承自父类的共性成员方法:
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b)
:将b.length
字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len)
:从指定的字节数组写入len
字节,从偏移量off
开始输出到此输出流。public abstract void write(int b)
:将指定的字节输出流。
- 构造方法:
BufferedOutputStream(OutputStream out)
:创建一个新的缓冲输出流,以将数据写入指定的底层输出流。BufferedOutputStream(OutputStream out, int size)
:创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。- 参数:
OutputStream out
:字节输出流。可以传递FileOutputStream
,缓冲流会给FileOutputStream
增加一个缓冲区,提高FileOutputStream
的写入效率。int size
:指定缓冲流内部缓冲区的大小,不指定采用默认。
- 使用步骤:
- 创建
FileOutputStream
对象,构造方法中绑定要输出的目的地。 - 创建
BufferedOutputStream
对象,构造方法中传递FileOutputStream
对象,提高FileOutputStream
对象效率。 - 使用
BufferedOutputStream
对象中的方法write
,把数据写入到内部缓冲区中。 - 使用
BufferedOutputStream
对象中的方法flush
,把内部缓冲区中的数据,刷新到文件中。 - 释放资源(
close
方法会先调用flush
方法刷新数据)。
- 创建
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("/Users/zgl/Desktop/a.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("zhuguli".getBytes());
bos.flush();
bos.close();
}
}
3. BufferedInputStream字节缓冲输入流
-
java.io.BufferedInputStream extends InputStream
-
BufferedInputStream
字节缓冲输入流。 -
继承自父类的成员方法:
int read()
:从输入流中读取数据的下一个字节并返回,读取到文件的末尾返回-1。int read(byte[] b)
:从输入流中读取一定数量的字节,并将其存储在缓冲区的数组b
中。void close()
:关闭此输入流并释放与该流关联的所有系统资源。
-
构造方法:
BufferedInputStream(InputStream in)
:创建一个BufferedInputStream
对象,并保存其参数,即输入流in
,以便将来使用。BufferedInputStream(InputStream in, int size)
:创建具有指定缓冲区大小的BufferedInputStream
并保存其参数,即输入流in
,以便将来使用。- 参数:
InputStream in
:字节输入流,可以传递FileInputStream
,缓冲流会给FileInputStream
增加一个缓冲区,提高FileInputStream
的读取效率。int size
:指定缓冲流内部缓冲区的大小,不指定默认。
-
使用步骤:
- 创建
FileInputStream
对象,构造方法中绑定要读取的数据源。 - 创建
BufferedInputStream
对象,构造方法中传递FileInputStream
对象,提高FileInputStream
对象读取效率。 - 使用
BufferedInputStream
对象中的方法read
,读取文件。 - 释放资源。
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("/Users/zgl/Desktop/a.txt"); BufferedInputStream bis = new BufferedInputStream(fis); /*int tmp; while ((tmp = bis.read()) != -1) { System.out.print((char)tmp); }*/ byte[] bytes = new byte[1024]; int len; while ((len = bis.read(bytes)) != -1) { System.out.println(new String(bytes,0,len)); } bis.close(); } }
- 创建
4. BufferedWriter字符缓冲输出流
java.io.BufferedWriter extends Writer
BufferedWriter
字符缓冲输出流。- 继承自父类的共性成员方法:
void write(int c)
:写入单个字符。void write(char[] cbuf)
:写入字符数组。void write(char[] cbuf, int off, int len)
:写入字符数组的某一部分,off
为数组的开始索引,len
为写的字符个数。void write(String str)
:写入字符串。void write(String str, int off, int len)
:写入字符串的某一部分,off
为字符串的开始索引,len
为写的字符个数。void flush()
:刷新该流的缓冲。void close()
:关闭此流,但要先刷新它。
- 构造方法:
BufferedWriter(Writer out)
:创建一个使用默认大小输出缓冲区的缓冲字符输出流。BufferedWriter(Writer out, int size)
:创建一个人使用给定大小缓冲区的新缓冲字符输出流。- 参数:
Writer out
:字符输出流,可以传递FileWriter
,缓冲流会给FileWriter
增加一个缓冲区,提高FileWriter
的写入效率。int size
:指定缓冲区的大小,不写采用默认大小。
- 特有的成员方法:
void newLine()
写入一个换行符。 - 使用步骤:
- 创建字符缓冲输出流对象,构造方法中传递字符输出流。
- 调用字符缓冲输出流中的方法
write
,把数据写入到内存缓冲区中。 - 调用字符缓冲输出流中的方法
flush
,把内存缓冲区中的数据刷新到文件中。 - 释放资源。
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("/Users/zgl/Desktop/b.txt");
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < 5; i++) {
bw.write("朱古力");
bw.newLine();
}
bw.flush();
bw.close();
}
}
5. BufferedRead字符缓冲输入流
java.io.BufferedReader extends Reader
- 继承自父类的共性成员方法:
int read()
:读取单个字符并返回。int read(char[] cbuf)
:一次读取多个字符,将字符读入数组。void close()
:关闭该流并释放与之关联的所有资源。
- 构造方法:
BufferedRead(Reader in)
:创建一个使用默认大小输入缓冲区的缓冲字符输入流。BufferedRead(Reader in, int size)
:创建一个使用指定大小输入缓冲区的缓冲字符输入流。- 参数:
Reader in
:字符输入流,可以传递FileReader
,缓冲流会给FileReader
增加一个缓冲区,提高FileReader
的读取效率。
- 特有的成员方法:
String readline()
读取一个文本行,读取一行数据。- 行的终止符号:通过下列字符之一即可认为某行已终止:
\n
、\r
、\r\n
。 - 返回值:包含该行内容的字符串,不包含任何行终止符。如果已到达流末尾,则返回
null
。
- 行的终止符号:通过下列字符之一即可认为某行已终止:
- 使用步骤:
- 创建字符缓冲输入流对象,构造方法中传递字符输入流。
- 使用字符缓冲输入流对象中的方法
read/readLine
读取文本。 - 释放资源。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("/Users/zgl/Desktop/b.txt");
BufferedReader br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
二、转换流
1. OutputStreamWriter
java.io.OutputStreamWriter extends Writer
OutputStreamWriter
:是字符流通向字节流的桥梁,可以使用指定的charset
将要写入流中的字符编码成字节。- 继承自父类的共性成员方法:
void write(int c)
:写入单个字符。void write(char[] cbuf)
:写入字符数组。void write(char[] cbuf, int off, int len)
:写入字符数组的某一部分,off
为数组的开始索引,len
为写的字符个数。void write(String str)
:写入字符串。void write(String str, int off, int len)
:写入字符串的某一部分,off
为字符串的开始索引,len
为写的字符个数。void flush()
:刷新该流的缓冲。void close()
:关闭此流,但要先刷新它。
- 构造方法:
OutputStreamWriter(OutputStream out)
:创建使用默认字符编码的OutputStreamWriter
。OutputStreamWriter(OutputStream out, String charsetName)
:创建使用指定字符集的OutputStreamWriter
。- 参数:
OutputStream out
:字节输出流,可以用来写转换之后的字节到文件中。String charsetName
:指定的编码表名称,不区分大小写,可以是utf-8
、UTF-8
、gbk
、GBK
…不指定默认使用UTF-8
。
- 使用步骤:
- 创建
OutputStreamWriter
对象,构造方法中传递字节输出流和指定的编码表名称。 - 使用
OutputStreamWriter
对象中的方法write
,把字符转换为字节存储到缓冲区中。 - 使用
OutputStreamWriter
对象中的方法flush
,把内存缓冲区中的字节刷新到文件中。 - 释放资源。
- 创建
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Test {
public static void main(String[] args) throws IOException {
write_utf_8();
write_gbk();
}
private static void write_gbk() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/zgl/Desktop/gbk.txt"), "gbk");
osw.write("你好");
osw.flush();
osw.close();
}
private static void write_utf_8() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/zgl/Desktop/utf_8.txt"), "utf-8");
osw.write("你好");
osw.flush();
osw.close();
}
}
2. InputStreamReader
java.io.InputStreamReader extends Reader
InputStreamReader
:是字节流通向字符流的桥梁,它是由指定的charset
读取字节并将其解码为字符。- 继承自父类的共性成员方法:
int read()
:读取单个字符并返回。int read(char[] cbuf)
:一次读取多个字符,将字符读入数组。void close()
:关闭该流并释放与之关联的所有资源。
- 构造方法:
InputStreamReader(InputStream in)
:创建一个使用默认字符集的InputStreamReader
。InputStreamReader(InputStream in, String charsetName)
:创建使用指定字符集的InputStreamReader
。- 参数:
InputStream in
:字节输入流,用来读取文件中保存的字节。String charsetName
:指定的编码表名称,不区分大小写,可以是utf-8
、UTF-8
、gbk
、GBK
…不指定默认使用UTF-8
。
- 使用步骤:
- 创建
InputStreamReader
对象,构造方法中传递字节输入流和指定的编码表名称。 - 使用
InputStreamReader
对象中的方法read
读取文件。 - 释放资源。
- 创建
- 注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
read_utf_8();
read_gbk();
}
private static void read_gbk() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/zgl/Desktop/gbk.txt"),
"gbk");
int tmp;
while ((tmp = isr.read()) != -1) {
System.out.println((char) tmp);
}
isr.close();
}
private static void read_utf_8() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/zgl/Desktop/utf_8.txt"),
"utf-8");
int tmp;
while ((tmp = isr.read()) != -1) {
System.out.println((char) tmp);
}
isr.close();
}
}
三、序列化流
1. 序列化与反序列化的概述
- 序列化:把对象以流的方式,写入到文件中保存,叫写对象,也叫对象的序列化。
- 对象中包含的不仅仅是字符,使用字节流。
ObjectOutputStream
:对象的序列化流。
- 反序列化:把文件中保存的对象,以流的方式读取出来,叫读对象,也叫对象的反序列化。
- 读取的文件保存的都是字节,使用字节流。
ObjectInputStream
:对象的反序列化流。
2. 对象的序列化流
java.io.ObjectOutputStream extends OutputStream
- 序列化和反序列化的时候,会抛出
NotSerializableException
没有序列化异常。- 类通过实现
java.io.Serializable
接口已启用其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化。 Serializable
接口也叫标记型接口。- 要进行序列化或反序列化的类必须实现
Serializable
接口,就会给类添加一个标记。 - 当我们进行序列化或反序列化的时候,就会检测类上是否有这个标记。
- 有:可以进行序列化或反序列化。
- 没有:就会抛出
NotSerializableException
没有序列化异常。
- 类通过实现
ObjectOutputStream
:对象的序列化流。- 作用:把对象以流的方式写入到文件中保存。
- 构造方法:
ObjectOutputStream(OutputStream out)
:创建写入指定OutputStream
的ObjectOutputStream
。- 参数:
OutputStream out
:字节输出流。
- 参数:
- 特有的成员方法:
void writeObject(Object obj)
将指定的对象写入ObjectOutputStream
。 - 使用步骤:
- 创建
ObjectOutputStream
对象,构造方法中传递字节输出流。 - 使用
ObjectOutputStream
对象中的方法writeObject
,把对象写入到文件中。 - 释放资源。
- 创建
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", 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;
}
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Test {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/zgl/Desktop/person.txt"));
oos.writeObject(new Person("zhuguli",18));
oos.close();
}
}
3. 对象的反序列化流
java.io.ObjectInputStream extends InputStream
ObjectInputStream
对象的反序列化流。- 作用:把文件中保存的对象,以流的方式读取出来使用。
- 构造方法:
ObjectInputStream(InputStream in)
创建从指定InputStream
读取的ObjectInputStream
。- 参数:
InputStream in
字节输入流
- 参数:
- 特有的成员方法:
Object readObject()
从ObjectInputStream
读取对象。- 该方法声明抛出了
ClassNotFoundException
异常,当不存在对象的class
文件时抛出此异常。
- 该方法声明抛出了
- 反序列化的前提:
- 类必须实现
Serializable
接口。 - 必须存在类对应的
class
文件。
- 类必须实现
- 使用步骤:
- 创建
ObjectInputStream
对象,构造方法中传递字节输入流。 - 使用
ObjectInputStream
对象中的方法readObject
读取保存对象的文件。 - 释放资源。
- 创建
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/zgl/Desktop/person.txt"));
Object o = ois.readObject();
ois.close();
System.out.println(o); // Person{name='zhuguli', age=18}
}
}
4. 瞬态关键字
static
关键字- 静态优先于非静态加载到内存中(静态优先于对象进入到内存中)。
- 被
static
修饰的成员变量是不能被序列化的,序列化的都是对象。
transient
关键字:瞬态关键字- 被
transient
修饰的成员变量是不能被序列化的。
- 被
5. 反序列化的InvalidClassException异常
-
每次修改类的定义,都会给
class
文件生成一个新的序列号。 -
可以在类中声明名为
serialVersionUID
的字段。-
格式:
static final long serialVersionUID = xL;
import java.io.Serializable; public class Person implements Serializable { static final long serialVersionUID = 42L; private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", 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; } }
-
四、打印流
java.io.PrintStream
打印流- 特点:
- 只负责数据的输出,不负责数据的读取。
- 与其他输出流不同,
PrintStream
永远不会抛出IOException
。 - 有特有的方法:
print
,println
。
- 与其他输出流不同,
- 只负责数据的输出,不负责数据的读取。
- 构造方法:
PrintStream(File file)
:输出的目的地是一个文件。PrintStream(OutputStream out)
:输出的目的地是一个字节输出流。PrintStream(String filename)
:输出的目的地是一个文件路径。
PrintStream extends OutputStream
- 继承自父类的方法:
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b)
:将b.length
字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len)
:从指定的字节数组写入len
字节,从偏移量off
开始输出到此输出流。public abstract void write(int b)
:将指定的字节输出流。
- 继承自父类的方法:
- 注意:
- 如果使用继承自父类的
write
方法写数据,那么查看数据的时候会查询编码表。 - 如果使用自己特有的
print\println
方法写数据,写的数据原样输出。
- 如果使用继承自父类的
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Test {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("/Users/zgl/Desktop/print.txt");
ps.write(97);
ps.println(97);
ps.close();
}
}
-
可以改变输出语句的目的地(打印流的流向)。
-
使用
System.setOut
方法改变输出语句的目的地改为参数中传递的打印流的目的地。static void setOut(PrintStream out)
重新分配”标准“输出流。
import java.io.FileNotFoundException; import java.io.PrintStream; public class Test { public static void main(String[] args) throws FileNotFoundException { System.out.println("控制台输出"); System.setOut(new PrintStream("/Users/zgl/Desktop/test.txt")); System.out.println("文件中输出"); } }