Java学习笔记 -IO流2
缓冲流 & 转换流
示例1 -BufferedReader
(1)知识点:
-
BufferedReader: 带有缓冲区的的字符输入流
使用这个流的时候不需要自定义char数组或者byte数组,自带缓冲 -
构造方法:BufferedReader(Reader in) 缓冲流的使用需要传递参数:字符流,字节流不行
-
概念:包装流 & 节点流
-
方法:readLine() 读取一行,会丢弃换行符,如果读取到文件结尾则返回null
(2)程序:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderTest01 {
public static void main(String[] args) {
BufferedReader br = null;
try {
//当一个流的构造方法需要一个流的时候:这个流称为节点流
//外部负责包装的流:包装流 或 处理流
FileReader reader = new FileReader("111.txt");
//参数必须是字符流不能是字节流
br = new BufferedReader(reader);
String s = null;
while ((s = br.readLine()) != null){
System.out.println(s);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例2 -转换流的使用
(1)知识点:
- 转换流:将字节流转换为字符流
- 构造方法:InputStreamReader(InputStream in)
(2)程序(没有处理异常):
public class BufferedReaderTest02 {
public static void main(String[] args) throws IOException {
//字节流
FileInputStream fis = new FileInputStream("111.txt");
//转换流:字节 -》 字符
InputStreamReader isr = new InputStreamReader(fis);
//缓冲流
BufferedReader br = new BufferedReader(isr);
String str = null;
while((str = br.readLine()) != null){
System.out.println(str);
}
br.close();
}
}
示例3 -BufferedWriter
- 构造方法:BufferedWriter(Writer out)
程序(没有处理异常):
public class BufferedWriteTest01 {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("111.txt",true)));
bw.write("Hellowordl\n");
bw.write("ddddrrrrr");
bw.flush();
bw.close();
}
}
数据流
-
数据流可以将数据连同数据类型一同写入文件,该文件不是普通的文本类型
-
DataOutStream写的文件,只能使用DataInputStream去读,
并且读取的顺序要和写入的顺序相同,才可以正常读出数据 -
构造方法:DataOutputStream(OutputStream out)
DataInputStream(InputStream in)
程序(没有处理异常):
public class DataOutputStreamTest01 {
public static void main(String[] args) throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));
byte b = 100;
short s = 200;
int i = 200;
char c = 'a';
//写入
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeChar(c);
dos.flush();
dos.close();
//=====================================================
DataInputStream dis = new DataInputStream(new FileInputStream("data"));
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readShort());
dis.close();
}
}
标准输出流
- java.io.PrintStream:标准的字节输出流,默认输出到控制台
- 标准输出流不需要手动关闭
- 标准输出流比较重要的就是:修改标准输出流的输出方向
程序:
public class PrintStreamTest {
public static void main(String[] args) throws FileNotFoundException {
//等价于 System.out.println("Hello World");
PrintStream ps = System.out;
ps.println("Hello World");
//标准输出流可以指定输出方向,指向"log"文件
PrintStream printStream = new PrintStream("log");
//修改输出方向,将输出方向修改到"log"文件
System.setOut(printStream);
System.out.println("hello kitty");
}
}
对象专属流
对象专属流的作用:
知识点:
-
参与序列化和反序列化的对象,必须实现Serializable接口
如果没有实现就将其序列化,会报异常:java.io.NotSerializableException -
Serializable接口只是一个标志性接口,什么代码都没有,只是起到标识的作用,给JVM看的
JVM看到Serializable接口之后,会为该类自动生成一个序列化版本号 -
序列化版本号
(1)java靠什么机制区分类?- 包名+类名
- 如果类名一样,则靠序列化版本号
(2)默认自动生成序列化版本号,但是这种方式有缺点:
- 一旦代码确定之后,不能进行后续的修改,
- 因为修改,则必然重新编译,此时生成全新的序列化版本号,这个时候JVM会认为这是一个全新的类
-
最终结论: 凡是一个类实现了Serializable接口,建议给该类手动分配一个序列化版本号
private static final long serialVersionUID = 1l;
-
transient关键字表示游离的,修饰的属性不参与序列化
-
如果存放多个对象,要使用集合的方式,如果一个一个序列化,则第二个会报错
示例程序:
import java.io.Serializable;
public class Student implements Serializable {
//手动分配
private static final long serialVersionUID = 1l;
//transient关键字表示游离的,修饰的属性不参与序列化
private transient String name;
private int age;
public Student() {}
public Student(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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectOutputStreamTest01 {
public static void main(String[] args) throws IOException {
//创建java对象
Student s = new Student("zhaosan",13);
Student s1 = new Student("ls",34);
List<Student> list = new ArrayList<>();
list.add(s);
list.add(s1);
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("studentClass"));
//序列化对象
oos.writeObject(list);
oos.flush();
oos.close();
}
}
public class ObjectInputStreamTest01 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("studentClass"));
//反序列化,读取类
List<Student> list = (List<Student>) ois.readObject();
for(Student s : list) {
System.out.println(s);
}
ois.close();
}
}