文件编码
java的字符串是双字节编码utf-16be,中英文字符都用两个字节来表示;utf-8中文3个字节英文一个字节;gbk中文2个字节英文一个字节。
文本文件是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化为byte的存储结构。
把字符序列变成字符串时需要使用相应的编码方式,否则会出现乱码。new String(byte[] b)是使用项目默认的编码方式。
问题:新建文本文档,输入“联通”保存后打开会出现乱码。
猜想:直接新建文本文档写入内容是按照ansi编码方式写入的,字符序列为“ c1 aa cd e8”,当文档中所有字符都在 C0≤AA≤DF 80≤BB≤BF 这个范围的时候,无法确认文档的格式。如果继续往文档添加内容再保存会发现文档的开头添加了"ef bb bf"的字符序列及其他东西,估计表示文档采用utf-8解析。
序列化和反序列化
对象序列化:将Object转换成byte序列,反之叫对象的反序列化。对象必须实现序列化接口(Serializable),才能进行序列化,否则将出现异常(NotSerializableException)。这个接口没有任何方法,只是一个标准。
序列化流(ObjectOutputStream)---writeObject
反序列化流(ObjectInputStream)---readObject
如果父类实现了Serializable接口,则子类也实现了该接口。对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被显示调用;如果其父类有实现序列化接口,则父类属性直接从存储处读取。
transient关键字修饰的属性不进行默认的序列化反序列化操作,可通过两个方法来自定义序列化和反序列化操作:
--》序列化
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
{
s.defaultWriteObject();//把jvm默认能序列化的元素进行序列化操作
//自定义序列化内容
}
--》反序列化
private void writeObject(java.io.ObjectInputStream s) throws java.io.IOException,ClassNotFoundException
{
s.defaultReadObject();//把jvm默认能反序列化的元素进行反序列化操作
//自定义反序列化内容
}
Arraylist的底层数组就是用transient修饰的,因为数组不一定填满,所以通过自定义writeObject和readObject两个方法来只将有效的元素进行序列化和反序列化操作,从而提高性能。
相关类介绍
(1)java.io.File:只用于表示文件或目录的信息(名称、大小等),不能用于文件内容的访问。
常用方法:
--》boolean isExists()
--》String[] list()
--》File[] listFiles()
--》Boolean createNewFile()
--》boolean mkdir()
--》boolean isDirectory():若文件不存在或者文件不是目录文件则返回false
(2)RandomAccessFile:可用于随机访问文件内容(访问文件的任意位置),既可以读文件,也可以写文件。
--》打开文件的两种模式:"rw"(读写),"r"(只读)
举例:
File f=new File("test.txt");
if(!f.isExists()){
f.createNewFile();
}
RandomAccessFile raf=new RandomAccessFile(f,"rw");
raf.write('A');//写入最后的一个字节,0x41
byte[] bs="文件".getBytes("gbk");
raf.write(bs);//写入字节数组,0x:ce c4 bc fe