黑马程序员_<<IO扩展对象和编码(序列化,管道流,字节(符)数组),随机访问文件>>


分类: IO流   116人阅读  评论(0)  收藏  举报

目录(?)[+]

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


1. 序列化对象

     1.概述

         对象被序列化后,然后存到硬盘的文件中,然后读取的时候可以方便的读取,要被存到硬盘文件中的对象类,必须实现接口Serializable接口,此接口中没有抽象方法,是为了标识类的。

        ObjectOutputStream的方法writeObject()和ObjectInputStream的方法readObject(),这两个方法是成对出现的,一个是写,一个是读。

      注意点:

         1.当被序列化的对象存到了硬盘上后,如果原来的类更改了,那么再次读取的时候,会读取失败,因为他们的标识ID被更改了,所以要向更改后,仍可以读取的话,那么在序列化的时候,指定固定的标识ID。static final long serialVersionUID = 42L;

        2.静态成员不能被序列化,因为序列化的都是在堆中,而静态的成员实在方法区中,如果非静态成员要向也不被序列化,那么由关键字:transient修饰,那么就会不被序列化。

        3.当文件中存储了多个对象,那么读取的时候没调用一次readObject方法,就读取一个对象。

     2.示例

        用序列标识号来标识类,那么原来的类更改了一些操作,那么也可以继续使用硬盘中被序列化的文件对象。

[java]  view plain copy
  1. import java.io.Serializable;  
  2.    
  3. public class Person implements Serializable {  
  4.    static final long serialVersionUID = 42L;  
  5.    private String name;  
  6.    int age;  
  7.    
  8.    public Person(String name, int age) {  
  9.      this.name = name;  
  10.      this.age = age;  
  11.    }  
  12.    
  13.    public String toString() {  
  14.      return name + ":" + age;  
  15.    }  
  16. }  
  17. import java.io.FileInputStream;  
  18. import java.io.FileNotFoundException;  
  19. import java.io.FileOutputStream;  
  20. import java.io.IOException;  
  21. import java.io.ObjectInputStream;  
  22. import java.io.ObjectOutputStream;  
  23.    
  24. public class SerDemo {  
  25.    public static void main(String[] args) throws Exception {  
  26.    
  27.      // WritePerson();  
  28.      ReadPerson();  
  29.    }  
  30.    
  31.    /* 写 */  
  32.    private static void ReadPerson() throws IOException,FileNotFoundException,  
  33.         ClassNotFoundException {  
  34.      ObjectInputStream ois = new ObjectInputStream(new FileInputStream(  
  35.           "F:\\per.txt"));  
  36.      Person p = (Person) ois.readObject();  
  37.      System.out.println(p);  
  38.    }  
  39.    
  40.    /* 读 */  
  41.    private static void WritePerson() throws IOException,FileNotFoundException {  
  42.      ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(  
  43.           "F:\\per.txt"));  
  44.      oos.writeObject(new Person("zhangsan"23));  
  45.      oos.close();  
  46.    }  
  47.    
  48. }  
  49. 结果:  
  50. zhangsan:23  


 

至于静态成员和非静态成员被transient修饰,自己看以测试一下。

2. 管道流

将输入流和输出流。连接起来有两种方式:利用构造函数,或者用connect()方法。

[java]  view plain copy
  1. public class Write implements Runnable {  
  2.    private PipedOutputStream out = null;  
  3.    
  4.    public Write(PipedOutputStream out) {  
  5.      super();  
  6.      this.out = out;  
  7.    }  
  8.    
  9.    public void run() {  
  10.    
  11.      try {  
  12.         System.out.println("开始写入数据,等待");  
  13.         Thread.sleep(4000);  
  14.         out.write("guandao".getBytes());  
  15.         out.close();  
  16.      } catch (IOException e) {  
  17.         e.printStackTrace();  
  18.      } catch (InterruptedException e) {  
  19.         e.printStackTrace();  
  20.       }  
  21.    }  
  22.    
  23. }  
  24. import java.io.IOException;  
  25. import java.io.PipedInputStream;  
  26.    
  27.    
  28. public class Read implements Runnable {  
  29.    private PipedInputStream in = null;  
  30.    
  31.    public Read(PipedInputStream in) {  
  32.      this.in = in;  
  33.    }  
  34.    
  35.    public void run() {  
  36.    
  37.      try {  
  38.         System.out.println("没有数据可读");  
  39.         byte [] b=new byte[1024];  
  40.         int len=in.read(b);  
  41.         System.out.println("读到数据");  
  42.         System.out.println(new String(b,0,len));  
  43.      } catch (IOException e) {  
  44.         e.printStackTrace();  
  45.      }  
  46.    }  
  47.    
  48. }  
  49.    
  50. import java.io.IOException;  
  51. import java.io.PipedInputStream;  
  52. import java.io.PipedOutputStream;  
  53.    
  54. public class PideDemo {  
  55.    
  56.     
  57.    public static void main(String[] args)throws IOException {  
  58.      PipedOutputStream pds=new PipedOutputStream();  
  59.      PipedInputStream pis=new PipedInputStream();  
  60.      pds.connect(pis);//链接  
  61.         Write w=new Write(pds);  
  62.         Read r=new Read(pis);  
  63.         new Thread(w).start();  
  64.         new Thread(r).start();  
  65.    }  
  66.    
  67. }  
  68. 结果:  
  69. 开始写入数据,等待  
  70. 没有数据可读  
  71. 读到数据  
  72. guandao  


 

 

3.  RandomAccessFile

 

随机访问文件,自身具备读写方法

1.特点:

不是IO包中的子类,直接继承Object但是是IO包成员,既可以读也可以写。内部封装一个数组,通过指针进行操作。

可以通过getFilePointer()和seek()方法设置指针的位置

2. 读写原理:就是内部分装了字节输入流和输出流。

3.通过构造函数知,只能操作文件。有模式:r,rw,rws,rwdbv

4. 跳过指定的字节数skipBytes(n);只能向后跳

5.如果模式是r,不会创建文件,会去读一个已经存在的文件,不存在,则抛出异常。如果模式是rw,操作文件不存在,则自动创建,要是文件存在,则不会覆盖。

 

[java]  view plain copy
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.io.RandomAccessFile;  
  4.    
  5. public class RandomAccessFileDemo {  
  6.    public static void main(String[] args) throws IOException {  
  7.      RandomAccessFile raf = new RandomAccessFile(new File("F:\\demo.txt"),  
  8.           "rw");// 可读可写  
  9.      /*写*/  
  10.      raf.write("张三".getBytes());  
  11.      raf.write(23);  
  12.    
  13.      raf.close();  
  14.      raf = new RandomAccessFile(new File("F:\\demo.txt"), "rw");// 可读可写  
  15.      /*读*/  
  16.      byte[] b = new byte[4];  
  17.      int l = raf.read(b);  
  18.      System.out.println(new String(b, 0, l));  
  19.    }  
  20.    
  21. }  
  22.    


4. DataInputStream和DataOutputStream

是用来操作基本数据类型的类。

注意点:

 writeUTF方法是用来操作指定写入的编码是utf-8方式,但是他是修改版本,在此写入的文件,只能应此对象来读取,其他的对象是读取不出来的,因为是修改版的。

 

[java]  view plain copy
  1. public static void main(String[] args) throws IOException {  
  2.       
  3.      DataWrite();  
  4.      DataRead();  
  5.    }  
  6.    public static void DataWrite() throws IOException{  
  7.      DataOutputStream out=new DataOutputStream(new FileOutputStream("F:\\data.txt"));  
  8.        out.writeInt(123);  
  9.        out.writeBoolean(true);  
  10.        out.writeDouble(34.87);  
  11.        out.writeDouble(1.1);  
  12.        out.close();  
  13.    }  
  14.    public static void DataRead() throws IOException{  
  15.       DataInputStream in=new DataInputStream(new FileInputStream("F:\\data.txt"));  
  16.        int a=in.readInt();  
  17.        boolean b=in.readBoolean() ;  
  18.        double c=in.readDouble();  
  19.        in.close();  
  20.        System.out.println(a);  
  21.        System.out.println(b);  
  22.        System.out.println(c);  
  23.    }  
  24. 结果:  
  25. 123  
  26. true  
  27. 34.87  
  28.    


5.     ByteArrayInputStream和ByteArrayOutputStream

    

用于操作字节数组

这两个流对象操作的数组,没有使用系统资源(没有创建文件),所以不用关闭。

ByteArrayInputStream:不用定义数据目的,因为封装了一个可变的字节数组

在流操作的规律中:

源和目的除了:键盘和文件,还有内存,内存就是ByteArrayInputStream和ByteArrayOutputStream,就是操作字节数组流。

 

[java]  view plain copy
  1. public static void main(String[] args) throws IOException {  
  2.      ByteArrayInputStream in=new ByteArrayInputStream("abcd".getBytes());  
  3.      ByteArrayOutputStream out=new ByteArrayOutputStream();  
  4.      int ch=0;  
  5.      while((ch=in.read())!=-1){  
  6.         out.write(ch);  
  7.      }  
  8.      System.out.println(out.size());  
  9.      System.out.println(out.toString());  
  10.    }  


  

CharArrayReader和CharArrayWriter 这两个类和ByteArrayInputStream,ByteArrayOutputStream使用一样,只是一个操作字符数组另一个操作字节数组,

StringReader与StringWriter用法也一样,只是操作的字符串

 

注意点:writeTo(OutputStream out)方法可以把数组中的数据直接写到流中。

6.编码表

 ISO8859-1:属于单字节编码方式,主要是在0~255字符范围,只要在英语在英文上。

GBK/GBK2312:中文的编码方式,只要是标识汉字,

Unicod:使用的是16进制的编码方式。

UTF:可以是字符的长度是1-6字符,这样可以节约空间。兼容所有字符。

 

   转换流之间的编码

   编码表:就是把各个国家的文字全部用数字表示出来,应用于计算机,那么这样就形成了一个表,就是编码表

GBK:一个汉字站两个字节

UTF-8:一个汉字占三个字节

同样的编码方式要用同样的变法方式读取,否则会出现乱码


[java]  view plain copy
  1. public class Text {  
  2.   public static void main(String[] args) throws IOException {  
  3.     //writeTxt();  
  4.     readTxt();  
  5.   }  
  6.    
  7.   public static void writeTxt() throws IOException{  
  8.     OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream("F:\\utf.txt"),"utf-8");  
  9.        writer.write("大家好");  
  10.        writer.close();  
  11.   }  
  12.   public static void readTxt() throws IOException{  
  13.     InputStreamReader reader=new InputStreamReader(new FileInputStream("F:\\utf.txt"),"utf-8");  
  14.        char []bu=new char[20];  
  15.        int len=reader.read(bu);  
  16.        System.out.println(new String(bu,0,len));  
  17.        reader.close();  
  18.   }  
  19. }  
  20.    


7. 字符的编码和解码 

 

  编码:字符串变成字节数组String—》byte[]String.getBytes(charsetName);

解码:字节数组变成字符串byte[]->String    new String(byte[],chatsename)

 

[java]  view plain copy
  1. public class Text {  
  2.   public static void main(String[] args) throwsUnsupportedEncodingException  {  
  3.     String s1="你好";  
  4.     byte [] b1=s1.getBytes("GBK");  
  5.     System.out.println(Arrays.toString(b1));//编码表  
  6.      
  7.     //假如编码方式变了  
  8.     String s2=new String(b1,"ISO8859-1");  
  9.     System.out.println(s2);  
  10.     byte [] b2=s2.getBytes("ISO8859-1");  
  11.     System.out.println(Arrays.toString(b2));//编码表  
  12.      
  13.     System.out.println(new String(b1,"GBK"));  
  14.   }  
  15. }  
  16. 结果:  
  17. [-60, -29, -70, -61]  
  18. ????  
  19. [-60, -29, -70, -61]  
  20. 你好  


 

注意:如果是GBK和UTF-8,之间编码方式乱了,就不能还原,因为GBK和UTF-8编码的时候,一个汉字对应的字节数不一样,所以还原后的字节数不一样,所仍然会出现乱码。



 

8.字符编码-联通

[java]  view plain copy
  1. 因为”联通” 用GBK存的产生的二进制和UTF-8编码方式一致(巧合) 11000001 10101010 11001101  10101000 用UTF-8存储的话,  
  2. public class Text {  
  3.   public static void main(String[] args) throwsUnsupportedEncodingException  {  
  4.     String s1="联通";  
  5.     byte [] b1=s1.getBytes("GBK");  
  6.     for(byte b:b1){  
  7.       System.out.println(Integer.toBinaryString(b&255));//将其转换成二进制,然后取后八位  
  8.     }  
  9.      
  10.   }  
  11. }  
  12. 结果:  
  13. 11000001  
  14. 10101010  
  15. 11001101  
  16. 10101000  


 

从结果可以看出:原本是用GBK编码,但是而进行却符合UTF-8的编码方式,所以直接用UTF-8进行解码,那么解析出来的结果当然会是乱码。

解决方式:在联通前面加任意汉字。

UTF-8编码方式字节读取个数

 



-------------------- ASP.Net+Android+IOS开发 .Net培训 、期待与您交流! --------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值