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

      

        

  • 相关阅读:
    Linux Bash
    grep 及正则表达式
    Linux 文件系统
    Linux 操作系统基础
    常见的磁盘I/O和网络I/O优化技巧
    NIO的工作方式
    网络I/O 工作机制
    spring Boot环境下dubbo+zookeeper的一个基础讲解与示例
    深入分析Java I/O 工作机制
    CDN工作机制和负载均衡
  • 原文地址:https://www.cnblogs.com/juncaoit/p/6918061.html
Copyright © 2020-2023  润新知