转换流:
使用转换流可以在一定程度上避免乱码,还可以指定输入输出所使用的字符集
InputStreamReader:是从字节流到字符流的桥梁,父类是Reader
OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer
转换流图解:
转换流的构造方法:
方法名 | 说明 |
---|---|
InputStreamReader(InputStream in) | 使用默认字符编码创建InputStreamReader对象 |
InputStreamReader(InputStream in,String chatset) | 使用指定的字符编码创建InputStreamReader对象 |
OutputStreamWriter(OutputStream out) | 使用默认字符编码创建OutputStreamWriter对象 |
OutputStreamWriter(OutputStream out,String charset) | 使用指定的字符编码创建OutputStreamWriter对象 |
public static void main(String[] args) throws IOException {
// JDK11前的方法
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/b.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/a.txt"), "UTF-8");
// JDK11后子字符流推出了新的构造方法
FileReader fr = new FileReader("/Users/itzhuzhu/Desktop/Java/ideaTest/io/a.txt", Charset.forName("gbk"));
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars)) != -1) {
osw.write(chars, 0, len);
}
osw.close();
isr.close();
}
对象操作流:
对象序列化:
将Java中的对象保存到文件中
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
- 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
- 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
构造方法
方法名 | 说明 |
---|---|
ObjectOutputStream(OutputStream out) | 创建一个写入指定的OutputStream的ObjectOutputStream |
序列化对象的方法
方法名 | 说明 |
---|---|
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream |
对象反序列化:
将文件中的对象,加载到程序中
构造方法
方法名 | 说明 |
---|---|
ObjectInputStream(InputStream in) | 创建从指定的InputStream读取的ObjectInputStream |
反序列化对象的方法
方法名 | 说明 |
---|---|
Object readObject() | 从ObjectInputStream读取一个对象 |
serialVersionUID:
序列化了一个对象后修改了对象再去读就会异常(InvalidClassException)
解决:给对象所属的类加一个serialVersionUID ,值随便定,不超Long就行
transient:
如果一个对象中的某个成员变量的值不想被序列化,就给成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
static: 被这个关键字修饰的成员变量在序列化时不会保存到文件中
-1&null的使用场景:
while ((len = bis.read(bytes)) != -1) { bos.write(bytes, 0, len); }
read():读取到文件末尾返回值是 ‐1
readLine():读取到文件的末尾返回值 null
readObject():读取到文件的末尾 直接抛出异常(把序列化的对象存储到集合中,把集合序列化到文件中)
代码演示:
// 把某个对象序列化就要把对象实现Serializable接口,但是不需要重写,因为Serializable没有方法,就是标记性接口
public class Student implements Serializable {
public static final long serialVersionUID = 1L;
private String username;
private transient String password;
public Student() {
}
public Student(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
测试类:
public class Demo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// write();
// read();
readArray();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/b.txt"));
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s);
ois.close();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/b.txt"));
Student s = new Student("itzhuzhu", "12345");
oos.writeObject(s);
oos.close();
}
//反序列化读取多个对象
private static void readArray() throws IOException, ClassNotFoundException {
Student s1 = new Student("韩信", "hanxin");
Student s2 = new Student("李白", "libai");
Student s3 = new Student("露娜", "luna");
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
// 创建序列化对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/b.txt"));
// 把对象装到集合再存到文件
oos.writeObject(list);
oos.close();
// 创建反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/itzhuzhu/Desktop/Java/ideaTest/io/b.txt"));
// 把文件里的对象数据读取到内存
ArrayList<Student> list2 = (ArrayList<Student>) ois.readObject();
for (Student student : list2) {
System.out.println(student);
}
ois.close();
}
}
打印流:
打印流分类:
字节打印流: PrintStream 字符打印流: PrintWriter
打印流的特点:
只有输出方向 让内容原样输出
构造方法:
- PrintStream(String fileName) 通过路径名字符串创建打印流
- PrintStream(File file) 通过File对象创建打印流
- PrintStream(OutputStream out) 通过OutputStream创建打印流
普通方法:
- void print(Xxx x) 打印后不换行
- void println(Xxx x) 打印后换行
public static void main(String[] args) throws FileNotFoundException {
// test01();
// out是System类中的一个静态成员变量,什么类型呢?PrintStream字节打印流
// 我们可以修改out的流向
System.out.println(65);
System.out.println("你好");
// 自己创建一个新的字节打印流
PrintStream ps = new PrintStream("day10demo\\abc\\oo.txt");
System.setOut(ps);
System.out.println("97");
System.out.println("大家好");
}
private static void test01() throws FileNotFoundException {
// 创建打印流
PrintStream ps = new PrintStream("day10demo\\abc\\ps.txt");
// 打印数据
ps.println(110);
ps.println(36.0d);
ps.println('好');
ps.println(true);
ps.println("真的好");
// 关闭流
ps.close();
}