IO知识点整理(序列化,管道流,数据流,字节数组流,与编码)

一:序列化的问题

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.结果

  

    

原文地址:https://www.cnblogs.com/juncaoit/p/6918061.html