一:序列化的问题
1.序列号的使用问题
关于在序列化中的序列号的使用问题,一般要是使用。
因为,每次要序列化的类产生都会产生一个一个新的序列号,如果将这个类的程序修改后,就会产生新的序列号,以前序列化后的文件将不会被读取。
所以,为了程序修改后,以前序列化后的程序仍然可以被读取,使用静态的序列号十分有必要。
2.将数据进行序列化
中在ObjectOutputStream类。
1 import java.io.FileOutputStream; 2 import java.io.ObjectOutputStream; 3 import java.io.Serializable; 4 5 public class Test114 { 6 7 public static void main(String[] args) throws Exception{ 8 writeObj(); 9 } 10 public static void writeObj() throws Exception{ 11 ObjectOutputStream objo=new ObjectOutputStream( 12 new FileOutputStream("op.txt")); 13 objo.writeObject(new People0("lisi",10)); 14 objo.close(); 15 } 16 } 17 18 class People0 implements Serializable{ 19 //序列号 20 public static final long serialVersionUID = 42L; 21 //属性 22 private String name; 23 private int age; 24 public People0(String name,int age){ 25 this.name=name; 26 this.age=age; 27 } 28 public String toString() { 29 return name+":"+age; 30 } 31 }
3.运行结果
4.读序列化后的文件
1 import java.io.FileInputStream; 2 import java.io.FileOutputStream; 3 import java.io.ObjectInputStream; 4 import java.io.ObjectOutputStream; 5 import java.io.Serializable; 6 7 public class Test114 { 8 9 public static void main(String[] args) throws Exception{ 10 //writeObj(); 11 readObj(); 12 } 13 public static void readObj() throws Exception{ 14 ObjectInputStream readObj=new ObjectInputStream( 15 new FileInputStream("op.txt")); 16 People0 p=(People0)readObj.readObject(); 17 //因为有toString方法,所以可以直接打印 18 System.out.println(p); 19 // 20 readObj.close(); 21 } 22 public static void writeObj() throws Exception{ 23 ObjectOutputStream objo=new ObjectOutputStream( 24 new FileOutputStream("op.txt")); 25 objo.writeObject(new People0("lisi",10)); 26 objo.close(); 27 } 28 } 29 30 class People0 implements Serializable{ 31 //序列号 32 public static final long serialVersionUID = 42L; 33 //属性 34 private String name; 35 private int age; 36 public People0(String name,int age){ 37 this.name=name; 38 this.age=age; 39 } 40 public String toString() { 41 return name+":"+age; 42 } 43 }
5.运行结果
6.不能序列化的情况
类中的static不能够序列化,因为static的属性在方法区,而序列化主要是序列化的是栈里的文件数据。
同时transient修饰的属性不能够序列化。
7.不能序列化的程序演示
1 import java.io.FileInputStream; 2 import java.io.FileOutputStream; 3 import java.io.ObjectInputStream; 4 import java.io.ObjectOutputStream; 5 import java.io.Serializable; 6 7 public class Test114 { 8 9 public static void main(String[] args) throws Exception{ 10 //writeObj(); 11 readObj(); 12 } 13 public static void readObj() throws Exception{ 14 ObjectInputStream readObj=new ObjectInputStream( 15 new FileInputStream("op.txt")); 16 People0 p=(People0)readObj.readObject(); 17 //因为有toString方法,所以可以直接打印 18 System.out.println(p); 19 // 20 readObj.close(); 21 } 22 public static void writeObj() throws Exception{ 23 ObjectOutputStream objo=new ObjectOutputStream( 24 new FileOutputStream("op.txt")); 25 objo.writeObject(new People0("lisi",10,"usa")); 26 objo.close(); 27 } 28 } 29 30 class People0 implements Serializable{ 31 //序列号 32 public static final long serialVersionUID = 42L; 33 //属性 34 private String name; 35 //添加transient的修饰 36 private transient int age; 37 //新加static 38 private static String contry="cn"; 39 public People0(String name,int age,String contry){ 40 this.name=name; 41 this.age=age; 42 this.contry=contry; 43 } 44 public String toString() { 45 return name+":"+age+":"+contry; 46 } 47 }
8.运行结果
运行的顺序是,先序列化,序列化后生成新的文件后,再进行反序列化。
这时,才会发现static与transient都没有被序列化。
二:管道流与RandomAccessFile
1.管道流
可以将读写进行相连。
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。
通常,数据由某个线程从 PipedInputStream
对象读取,并由其他线程将其写入到相应的 PipedOutputStream
。
不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。
2.管道流程序(多线程)
1 import java.io.IOException; 2 import java.io.PipedInputStream; 3 import java.io.PipedOutputStream; 4 5 public class Test115 { 6 7 public static void main(String[] args) throws Exception { 8 PipedInputStream in=new PipedInputStream(); 9 PipedOutputStream out=new PipedOutputStream(); 10 in.connect(out); //链接connect 11 12 Writer w=new Writer(out); 13 Reader r=new Reader(in); 14 new Thread(w).start(); 15 new Thread(r).start(); 16 } 17 18 } 19 class Writer implements Runnable{ 20 private PipedOutputStream out; 21 public Writer(PipedOutputStream out){ 22 this.out=out; 23 } 24 public void run(){ 25 try{ 26 Thread.sleep(5000); 27 out.write("sjhdbs".getBytes()); 28 out.close(); 29 }catch(Exception e){ 30 e.toString(); 31 } 32 } 33 } 34 class Reader implements Runnable{ 35 private PipedInputStream in; 36 public Reader(PipedInputStream in){ 37 this.in=in; 38 } 39 public void run(){ 40 try{ 41 byte[] buf=new byte[1024]; 42 int len=in.read(buf); 43 String str=new String(buf,0,len); 44 System.out.println("str="+str); 45 in.close(); 46 }catch(Exception e){ 47 e.toString(); 48 } 49 } 50 }
3.运行结果
4.RandomAccessFile
该类不是算是IO体系中子类。
而是直接继承自Object。
但是它是IO包中成员。因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,
同时可以通过seek改变指针的位置。
通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,,读写rw等。
5.写入程序
在程序中使用writeInt,这个方法是每次写入4个字节,如果使用write则是每次写入1个字节。
考虑到数字的越界,这里使用writeInt方法。
这个方法的写方式在下面的程序中没有什么特殊的地方。
1 import java.io.FileNotFoundException; 2 import java.io.RandomAccessFile; 3 4 public class Test116 { 5 public static void main(String[] args) throws Exception{ 6 randomWrite(); 7 } 8 /** 9 * 简单的写入 10 * @throws Exception 11 */ 12 public static void randomWrite() throws Exception{ 13 RandomAccessFile raf=new RandomAccessFile("pu.txt","rw"); 14 raf.write("张三".getBytes()); 15 raf.writeInt(97); 16 raf.write("李四".getBytes()); 17 raf.writeInt(20); 18 raf.close(); 19 } 20 }
6.结果
7.分别使用seek与skipBytes的读方式(待探求为啥读取有问题)
1 import java.io.FileNotFoundException; 2 import java.io.RandomAccessFile; 3 4 public class Test117 { 5 6 public static void main(String[] args) throws Exception{ 7 System.out.println("seek function"); 8 randomReadSeek(); 9 System.out.println("skipBytes function"); 10 randomReadSkipbytes(); 11 } 12 /** 13 * seek function 14 * @throws Exception 15 */ 16 public static void randomReadSeek() throws Exception{ 17 RandomAccessFile raf=new RandomAccessFile("pu.txt", "r"); 18 raf.seek(0); 19 byte[] buf = new byte[8]; 20 21 raf.read(buf); 22 23 String name = new String(buf); 24 25 int age = raf.readInt(); 26 27 28 System.out.println("name="+name); 29 System.out.println("age="+age); 30 31 raf.close(); 32 } 33 public static void randomReadSkipbytes()throws Exception{ 34 RandomAccessFile raf=new RandomAccessFile("pu.txt", "r"); 35 raf.skipBytes(2); 36 byte[] buf = new byte[8]; 37 38 raf.read(buf); 39 40 String name = new String(buf); 41 42 int age = raf.readInt(); 43 44 45 System.out.println("name="+name); 46 System.out.println("age="+age); 47 48 raf.close(); 49 } 50 51 52 }
三:数据流对象的操作
1.关于DataInputStream与DataOutputStream的介绍
其主要是将数据与流进行结合。
2.写数据程序
1 import java.io.DataInputStream; 2 import java.io.DataOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 7 public class Test118 { 8 9 public static void main(String[] args) throws Exception { 10 dataWrite(); 11 12 } 13 public static void dataWrite()throws Exception{ 14 DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt")); 15 dos.writeInt(78); 16 dos.writeBoolean(true); 17 dos.writeDouble(89.90907); 18 dos.close(); 19 } 20 }
3.读的程序
注意点是,读取数据的时候,必须与写的数据类型相对应,保持读写的一致性。
1 import java.io.DataInputStream; 2 import java.io.DataOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 7 public class Test118 { 8 9 public static void main(String[] args) throws Exception { 10 //dataWrite(); 11 dataRead(); 12 } 13 public static void dataRead() throws Exception{ 14 DataInputStream dis=new DataInputStream(new FileInputStream("data.txt")); 15 int num=dis.readInt(); 16 boolean state=dis.readBoolean(); 17 double twonum=dis.readDouble(); 18 System.out.println("num="+num+",state="+state+",twonum="+twonum); 19 } 20 public static void dataWrite()throws Exception{ 21 DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt")); 22 dos.writeInt(78); 23 dos.writeBoolean(true); 24 dos.writeDouble(89.90907); 25 dos.close(); 26 } 27 }
4.运行结果
5.关于DataInputStream中的writeUIF的特殊性(包含readUIF)
所以在下面,通过程序进行验证。
6.带编码的可以读写字串的程序
1 import java.io.DataInputStream; 2 import java.io.DataOutputStream; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class Test119 { 7 8 public static void main(String[] args)throws Exception { 9 writeUtf(); 10 readUtf(); 11 } 12 public static void writeUtf()throws Exception{ 13 DataOutputStream dos=new DataOutputStream(new FileOutputStream("string.txt")); 14 dos.writeUTF("shdfcsdcnklbsnkl"); 15 dos.close(); 16 } 17 public static void readUtf()throws Exception{ 18 DataInputStream dis=new DataInputStream(new FileInputStream("String.txt")); 19 String str=dis.readUTF(); 20 System.out.println("str="+str); 21 } 22 23 }
7.运行结果
8.使用FileOutputStream的编码方式对字符串的读写
1 import java.io.FileNotFoundException; 2 import java.io.FileOutputStream; 3 import java.io.OutputStream; 4 import java.io.OutputStreamWriter; 5 import java.io.UnsupportedEncodingException; 6 7 public class Test120 { 8 public static void main(String[] args) throws Exception{ 9 OutputStreamWriter fos=new OutputStreamWriter(new FileOutputStream("gnk.txt"),"gbk"); 10 fos.write("你好"); 11 fos.close(); 12 } 13 }
9.结果
四:字节数组流的操作
1.程序
1 /* 2 用于操作字节数组的流对象。 3 4 ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。 5 6 ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。 7 这就是数据目的地。 8 因为这两个流对象都操作的数组,并没有使用系统资源。 9 所以,不用进行close关闭。 10 在流操作规律讲解时: 11 源设备, 12 键盘 System.in,硬盘 FileStream,内存 ArrayStream。 13 目的设备: 14 控制台 System.out,硬盘FileStream,内存 ArrayStream。 15 用流的读写思想来操作数据。 16 */ 17 import java.io.*; 18 class ByteArrayStream 19 { 20 public static void main(String[] args) 21 { 22 //数据源。 23 ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes()); 24 //数据目的 25 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 26 27 int by = 0; 28 29 while((by=bis.read())!=-1) 30 { 31 bos.write(by); 32 } 33 System.out.println(bos.size()); 34 System.out.println(bos.toString()); 35 } 36 }
五:编码
1.介绍
编码:将字符串变成字节数组
解码:将字节数组变成字符串
String-->byte[]; str.getBytes(charsetName);
byte[] -->String: new String(byte[],charsetName);
2.程序
1 import java.util.Arrays; 2 3 public class Test121 { 4 public static void main(String[] args)throws Exception { 5 String str="嘿嘿"; 6 byte[] buf1=str.getBytes("utf-8"); 7 //打印字节码 8 System.out.println(Arrays.toString(buf1)); 9 //utf-8解码 10 String s1=new String(buf1,"gbk"); 11 System.out.println("s1="+s1); 12 //再使用utf-8编码 13 byte[] buf2=s1.getBytes("gbk"); 14 System.out.println(Arrays.toString(buf2)); 15 //打印 16 String s2=new String(buf2,"utf-8"); 17 System.out.println("s2="+s2); 18 } 19 }
3.结果