转换流
字符编码
计算机中储存的信息都是用二进制数表示的,从屏幕上看到的字符十二进制转换的结果,按照某种规则储存到计算机中,称为编码; 反之,将储存在计算机中的二进制数按照某种规则解析显示出来称为解码.
字符编码; Character Encoding : 是自然语言的字符与二进制数之间对应的规则
字符集
- ASCII字符集: 用于显示现代英语,包括控制字符(回车键\换行键等)
- ISO-8859-1字符集: 用于显示欧洲使用的语言
- GB2312字符集: 简体中文码表 GBK : 最常用的中文码表 GB18030 : 最新的中文码表,还支持中国内少数民族的文字
- Unicode字符集:
该编码系统为表达任意语言的任意字符而设计,最多使用4个字节的数字来表示每个字母\符号或文字,有三种编码方案,UTF-8\UTF-16\UTF-32,其中UTF-8 最常用
由于编码的方式不同会引发的问题
InputSteamReader类
在创建流对象时指定字符集
如
InputStreamReader sad = new InputStreamReader(new FileInputStream("test.txt"), "GBK");
OutputSteamReader类
如
OutputStreamReader sad = new OutputStreamReader(new FileOutputStream("test.txt"), "GBK");
序列化
java中提供了一种对象序列化的机制,用一个字节序列可以表示一个对象,该字节序列包括对象的数据\对象的类型和对象中储存的属性等.字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息, 反之, 该字节序列还可以从文件中读取出来,重构对象,对它进行反序列化,对象的数据\对象的类型和对象中储存的数据信息,都可以用来在内存中创建对象
ObjectOutputStream 类
ObjectOutputStream(OutputStream out) : 创建一个指定 OutputStream 的 ObjectOutputStream
构造方法:
FileOutputStream fileout = new FileOutputStream("test.txt");
ObjectOutputStream out = new ObjectOutputStream(fileout);
序列化操作
- 一个对象要序列化,必须满足两个条件:
该类必须实现 Serializable 接口,Serializable 是一个标记接口,不识闲此接口的类将不会是任何状态序列化或反序列化, 会抛出 NotSerializableException的异常
该类的所有属性必须是可序列化的,如果有一个属性不需要序列化,则该属性必须注明是瞬间的,使用 transient 关键字修饰
class SerializableDemoss implements Serializable{
public String name;
public String add;
public transient int age; //transient修饰,不会被序列化
public void addre(){
System.out.println("add : " + name + " --- " + add);
}
}
- 写出对象: writeObject(Object obj):指定的对象写出
import java.io.*;
public class ObjectWriteFileDemo {
public static void main(String[] args){
SerializableDemoss ser = new SerializableDemoss();
ser.name = "xiaohong";
ser.add = "dongdalu";
ser.age = 13;
try{
FileOutputStream fileout = new FileOutputStream("G:\\mmm.txt");
ObjectOutputStream objects = new ObjectOutputStream(fileout);
objects.writeObject(ser);
//关闭资源
objects.close();
fileout.close();
System.out.println("此时年龄没有被序列化");
}catch (IOException e){
e.printStackTrace();
}
ser.addre();
}
}
注意:输出是对象输出,不是字符串,看起来想乱码的样子
ObjectInputStream类
ObjectInuptStream(InputStream in) : 创建一个指定的 InuptStream 的 ObjectInputStream
反序列操作1
如果一个对象的class 文件,可以进行反序列化操作,调用 ObjectInputStream 读取对象的方法:
readObject() : 读取一个对象
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class FileObjectDemoTwo {
public static void main(String[] args){
SerializableDemoss sd = null;
try{
FileInputStream filein = new FileInputStream("G:\\mmm.txt");
ObjectInputStream os = new ObjectInputStream(filein);
//读取一个对象
sd = (SerializableDemoss) os.readObject();
os.close();
filein.close();
} catch(IOException e){
e.printStackTrace();
return;
}catch (ClassNotFoundException c){
System.out.println("类找不到");
c.printStackTrace();
return;
}
//无异常输出
System.out.println("name: " + sd.name);
System.out.println("add: " + sd.add);
System.out.println("age: " + sd.age);
}
}
输出:
反序列操作2
JVM反序列化对象时,能找到 class 文件,但是 class 文件在序列化对象之后发生了修改,那么反序列化操作也会失败, 会抛出一个 InvalidClassException 异常
该类的序列版本号与从流中读取的类描述符的版本号胡匹配
该类包含未知数据类型
该类没有可访问的无参数构造方法
Serializable 接口给需要序列化的类,提供了一个序列版本号, serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配
class SerializableDemoss implements Serializable{
//加入序列版本号
private static final long serialVersionUID = 1L;
public String name;
public String add;
public transient int age; //transient修饰,不会被序列化
//添加新的属性,重新编译,可以反序列化,该属性赋为默认值
public int ers;
public void addre(){
System.out.println("add : " + name + " --- " + add);
}
}
打印流
PrintStream(String filename) : 使用指定的文件名创建一个新的打印流
PrintStream ps = new PrintStream("abc.txt");
System.out 就是 PrintStream 类型的,可以改变流向
import java.io.PrintStream;
public class PrintStreamDemo {
public static void main(String[] args) throws Exception{
//System.out 是直接打印在控制台
System.out.println(30000);
//创建打印流,指定文件名
PrintStream ps = new PrintStream("G:\\789.txt");
//设置系统的打印流向,输出到 789.txt
System.setOut(ps);
//调用系统打印流,789.txt中输出
System.out.println(30000);
}
}
输出:
文件中输出: