file (三)

字符串的序列化(文字的编码方案)
 从char序列到byte序列 的转换,叫"编码"
 1) String 字符串本质上是Char
 
 2)utf-16be 编码-----将16位char从中间切开为2个byte
     utf -16be是将 unicode char[] 序列化为byte[]的编码方案
     能够支持65535个字符编码,英文浪费空间

 如:
 char[] = ['A',    'B',    '中']
  对应     0041,0042,4e2d

 utf-8:国际标准,是将unicode编码为byte序列的方案,采用变长编码 1-N方案,其中英文1个byte,中文3个byte
   unicoded的" 中": 4e 2d = 01001110 00101101
    utf-8的"中":e4 b8 ad =11100100 10111000 10101101
        1110xxxx 10xxxxxx 10xxxxxx

 以0开头的是英文(0-127)
 110表示连续2字节表示一个字符
 1110表示连续3字节表示一个字符
 每个数据字节以10开头

GBK: 中国标准,支持20000+中日韩文,英文编码1byte,中文2byte
 与unicode不兼容,中文windows默认gbk

ISO8859-1:只支持255个英文字符,不支持中文(Sun服务器默认编码,如tomcat等)

例子

复制代码
 1 import java.io.FileOutputStream;
 2 import java.io.IOException;
 3 import java.io.OutputStream;
 4 
 5 public class CharIODemo {
 6  public static void main(String[] args) 
 7   throws IOException{
 8   String str = "ABCD中国";
 9   System.out.println(str);
10   //Java 的字符是16位 Unicode值,而文件是8位Byte序列
11   
12   //GBK
13   System.out.println("GBK编码方案,对字符编码");
14   String file = "gbk.txt";
15   OutputStream out = new FileOutputStream(file);//默认GBK编码方案
16   byte[] gbk = str.getBytes("GBK");
17   out.write(gbk);
18   out.close();
19   IOUtils.print(file);
20   //UTF-16BE,每个编码是2个字节
21   System.out.println("UTF-16BE编码方案,对字符编码");
22   file = "utf-16be.txt";
23   out = new FileOutputStream(file);
24   byte[] utf16be = str.getBytes("UTF-16BE");
25   out.write(utf16be);
26   out.close();
27   IOUtils.print(file);
28   
29   //UTF-8,英文是1个字节,中文是3个字节
30   System.out.println("UTF-8编码方案,对字符编码");
31   file = "utf-8.txt";
32   out = new FileOutputStream(file);
33   byte[] utf8 = str.getBytes("UTF-8");//编码string -> byte[]
34   out.write(utf8);
35   out.close();
36   IOUtils.print(file);
37   
38   byte[] buf = IOUtils.read("utf-8.txt");
39   //new String(buf,"UTF-8"),构造器可以将 byte编码序列
40   //解码为 char序列(字符串)
41   String s = new String(buf,"UTF-8");//解码byte-> String
42   System.out.println(s);
43  }
44 }
复制代码

 

6 字符流IO(Reader Writer)
1) 字符的处理,一次处理一个字符(unicode编码)
2) 字符的底层仍然是基本的字节流
3) 字符流的基本实现

 InputStreamReader 完成byte流解析为char流,按照编码解析
 OutputStreamWriter 提供char流到byte流,按照编码处理
4) 字符流的过滤器
    是字符读写的功能扩展,极大的方便了文本的读写操作
    BufferedReader : readLine()   一次读取一行
    PrintWriter : println()  一次打印一行
5)读取一个文本文件
 InputStream is = new FileInputStream("test.txt");
 Reader in = new InputStreamReader(is);
 BufferedReader reader = new BufferedReader(in);
 或者
 BufferedReader in = new BufferedReader(new FileReader(filename));

例子:

复制代码
 1 import java.io.BufferedInputStream;
 2 import java.io.BufferedReader;
 3 import java.io.FileInputStream;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 
 7 public class TestReaderDemo {
 8  public static void main(String[] args) 
 9   throws IOException{
10   //Scanner BufferedReader都是流的功能扩展,是过滤器
11   // 不能单独使用,最终需要依赖于基本byte流(in)
12   //Scanner 提供了nextLine()方法//Java5以后
13   //BufferedReader 提供了 readLine()方法,读取一行
14   //readLine()读取到文件末尾返回null
15   
16   //逐行读取文本文件,显示到系统控制台
17   //工作中常用
18   String file = "in.txt"; //为当前工作区workspace/项目名/in.txt
19   BufferedReader in = new BufferedReader(
20     new InputStreamReader(
21       new BufferedInputStream(
22         new FileInputStream(file)),"gbk"));
23   String str;
24   while((str = in.readLine()) != null){
25    System.out.println(str);
26   }
27   in.close();
28  }
复制代码

 


6)写出一个文本文件
 PrintWriter out = new PrintWriter(new FileWriter(new FileOutputStream(filename)));
 或者
 PrintWriter out = new PrintWriter(
     new OutputStreamWriter(
      new FileOutputStream(filename)))
例子

复制代码
 1 import java.io.IOException;
 2 import java.io.PrintWriter;
 3 import java.util.Scanner;
 4 
 5 public class SyncWriteDemo {
 6  public static void main(String[] args) 
 7   throws IOException{
 8   Scanner in = new Scanner(System.in);
 9   String file = "sync.txt";
10   PrintWriter out = new PrintWriter(file,"UTF-8");
11   while(true){
12    String str = in.nextLine();
13    out.println(str);
14    if("q".equalsIgnoreCase(str)){
15     break;
16    }
17   }
18   out.close();
19  }
20 }
复制代码

 

7)系统的默认编码,中文一般是GBK
如何查看默认编码?

String encoding = System.getProperty("file.encoding");

 


7 对象的IO序列化和深层复制

什么是对象序列化:
 将对象Object转换为byte序列,反之叫做对象的反序列华
1)序列化流,是过滤流
 ObjectOutputStream   方法 writeObject()  对象的序列化
 ObjectInputStream     方法readObject()  对象的反序列化
2)序列化接口(Serializable)


   对象必须实现"序列化接口Serializable"才能进行序列化,否则将出现不能序列化的异常
 Serializable是一个空的接口,没有任何方法 ,仅作为序列化的一个标识


3)JavaBean 规范规定,Java类必须实现Serializable接口


   Java API中的类大多是符合Java Bean规范的,基本都实现了Serializable


4) 对象的序列化可以变相实现对象的深层复制
例子

复制代码
 1 import java.io.BufferedInputStream;
 2 import java.io.BufferedOutputStream;
 3 import java.io.FileInputStream;
 4 import java.io.FileOutputStream;
 5 import java.io.ObjectInputStream;
 6 import java.io.ObjectOutputStream;
 7 import java.io.Serializable;
 8 
 9 public class ObjectIODemo {
10  public static void main(String[] args) 
11   throws Exception{
12   String file = "obj.dat";
13   ObjectOutputStream out = new ObjectOutputStream(
14     new BufferedOutputStream(
15       new FileOutputStream(file)));
16   Foo foo =new Foo();
17   out.writeObject(foo);//将foo引用的对象,序列化到文件中
18   out.close();
19   
20   //读出
21   ObjectInputStream in = new ObjectInputStream(
22     new BufferedInputStream(
23       new FileInputStream(file)));
24   Foo foo1 = (Foo)in.readObject();//对象反序列化
25   in.close();
26   System.out.println(foo1.name);
27 
28   System.out.println("深层复制:对象被复制,对象属性也被复制");
29   System.out.println(foo==foo1);//false 对象复制了(一层)
30   System.out.println(foo.name == foo1.name);//false ,属性被复制了(二层)
31   //利用序列化 和 反序列化  可以简洁的实现 对象的深层复制
32  }
33 
34 }
35 class Foo implements Serializable{//Serializable没有声明方法
36  String name = "Tom";
37 }
复制代码

 


浅层复制与深层复制
1)java的默认规则是浅层复制,性能好,但隔离性差,如(clone(),Arrays.copyOf)
 浅层复制 : 对象的引用不同,但对象中属性的引用相同
2)利用序列化可以实现深层复制
 深层复制: 对象的引用不同,但对象中的属性的引用也不相同

复制代码
 1 import java.io.ByteArrayInputStream;
 2 import java.io.ByteArrayOutputStream;
 3 import java.io.ObjectInputStream;
 4 import java.io.ObjectOutputStream;
 5 
 6 public class DeepcopyDemo {
 7  public static Object deepCope(Object obj){
 8   try{
 9    //1. 对象序列化
10    // 缓冲流: 字节数组输出流
11    ByteArrayOutputStream buf =
12     new ByteArrayOutputStream();
13    //对象输出流
14    ObjectOutputStream out = 
15     new ObjectOutputStream(
16       new ByteArrayOutputStream());
17    
18    out.writeObject(obj);//序列化对象到buf中
19    out.close();
20    
21    //2 .对象的反序列化
22    byte[] ary = buf.toByteArray();
23    ByteArrayInputStream bais = 
24     new ByteArrayInputStream(ary);
25    ObjectInputStream in = 
26     new ObjectInputStream(bais);
27    Object o = in.readObject();//从ary反序列化
28    in.close();
29    return o;
30    
31   }catch(Exception e){
32    e.printStackTrace();
33    throw new RuntimeException(e);
34   }
35  }
36 }
复制代码

 

以上用到的ByteArrayInputStreamByteArrayOutputStream

下面有一个ByteArrayInputStream和ByteArrayOutputStream的例子

例子

复制代码
 1 import java.io.ByteArrayInputStream;
 2 import java.io.ByteArrayOutputStream;
 3 import java.io.IOException;
 4 import java.util.Arrays;
 5 
 6 import com.tarena.day18.IOUtils;
 7 
 8 public class ByteArrayIODemo {
 9  public static void main(String[] args) 
10   throws IOException{
11   byte[] ary = {1,-1,127,-128};
12   //   {00000001, 11111111, 01111111, 10000000}
13   ByteArrayInputStream in = new ByteArrayInputStream(ary);
14   int b = in.read();//1 00000000 00000000 00000000 00000001
15   System.out.println(b);
16   b = in.read();
17   System.out.println(b);//255   00000000 00000000 00000000 11111111
18   b = in.read();   
19   System.out.println(b);//127   00000000 00000000 00000000  01111111
20   b = in.read();
21   System.out.println(b);//128   00000000 00000000 00000000  10000000
22   b = in.read();
23   System.out.println(b);//-1    11111111  11111111  11111111  11111111
24   in.close();
25   
26   ByteArrayOutputStream out = new ByteArrayOutputStream();//默认开辟32byte的数组作为输出目标
27   //如果满了就自动扩容
28   //out:[0,0,0,0,0,0,0,.....]
29   //
30   out.write(1);//[1,0,0,0,0,0,....]
31   out.write(-2);//[1,fe,0,0,0,0,0,....]
32   out.write(-1);//[1,fe,ff,0,0,0,0,....]
33   out.close();
34   byte[] buf = out.toByteArray();//复制有效部分
35   IOUtils.print(buf);//[01, fe, ff ]
36  }
37 
38 }
39 
40 
41  
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值