java IO(三):数据操作流、合并流、回退流、对象序列化、字符编码问题、压缩流

来源:互联网 发布:hbase查找数据方式 编辑:程序博客网 时间:2024/06/05 06:29

数据操作流

   在io包中,提供了两个与平台无关的数据操作流:

  • 数据输入流(DataInputStream)
  • 数据输出流(DataOutputStream)
   通常数据输出流会按一定格式将数据输出,再通过数据输入流按照一定格式将数据读入

   

  DataOutputStream接口定义了一系列的writeXxx()的操作,可以写入各种数据类型的数据。

范例:使用数据操作流写入 与 读出数据


import java.io.DataOutputStream ;import java.io.File ;import java.io.FileOutputStream ;public class DataOutputStreamDemo{public static void main(String args[]) throws Exception{// 所有异常抛出DataOutputStream dos = null ;// 声明数据输出流对象File f = new File("d:" + File.separator + "order.txt") ; // 文件的保存路径dos = new DataOutputStream(new FileOutputStream(f)) ;// 实例化数据输出流对象String names[] = {"衬衣","手套","围巾"} ;// 商品名称float prices[] = {98.3f,30.3f,50.5f} ;// 商品价格int nums[] = {3,2,1} ;// 商品数量for(int i=0;i<names.length;i++){// 循环输出dos.writeChars(names[i]) ;// 写入字符串dos.writeChar('\t') ;// 写入分隔符dos.writeFloat(prices[i]) ; // 写入价格dos.writeChar('\t') ;// 写入分隔符dos.writeInt(nums[i]) ; // 写入数量dos.writeChar('\n') ;// 换行}dos.close() ;// 关闭输出流}};
import java.io.DataInputStream ;import java.io.File ;import java.io.FileInputStream ;public class DataInputStreamDemo{public static void main(String args[]) throws Exception{// 所有异常抛出DataInputStream dis = null ;// 声明数据输入流对象File f = new File("d:" + File.separator + "order.txt") ; // 文件的保存路径dis = new DataInputStream(new FileInputStream(f)) ;// 实例化数据输入流对象String name = null ;// 接收名称float price = 0.0f ;// 接收价格int num = 0 ;// 接收数量char temp[] = null ;// 接收商品名称int len = 0 ;// 保存读取数据的个数char c = 0 ;// '\u0000'try{while(true){temp = new char[200] ;// 开辟空间len = 0 ;while((c=dis.readChar())!='\t'){// 接收内容temp[len] = c ;len ++ ;// 读取长度加1}name = new String(temp,0,len) ;// 将字符数组变为Stringprice = dis.readFloat() ;// 读取价格dis.readChar() ;// 读取\tnum = dis.readInt() ;// 读取intdis.readChar() ;// 读取\nSystem.out.printf("名称:%s;价格:%5.2f;数量:%d\n",name,price,num) ;}}catch(Exception e){}dis.close() ;}};

合并流

    从概念上讲就是把内容合并在一起了。



使用范例:

import java.io.File ;import java.io.SequenceInputStream ;import java.io.FileInputStream ;import java.io.InputStream ;import java.io.FileOutputStream ;import java.io.OutputStream ;public class SequenceDemo{public static void main(String args[]) throws Exception {// 所有异常抛出InputStream is1 = null ;// 输入流1InputStream is2 = null ;// 输入流1OutputStream os = null ;// 输出流SequenceInputStream sis = null ;// 合并流is1 = new FileInputStream("d:" + File.separator + "a.txt") ;is2 = new FileInputStream("d:" + File.separator + "b.txt") ;os = new FileOutputStream("d:" + File.separator + "ab.txt") ;sis = new SequenceInputStream(is1,is2) ;// 实例化合并流int temp = 0 ;// 接收内容while((temp=sis.read())!=-1){// 循环输出os.write(temp) ;// 保存内容}sis.close() ;// 关闭合并流is1.close() ;// 关闭输入流1`is2.close() ;// 关闭输入流2os.close() ;// 关闭输出流}};

回退流

在Java IO中所有的数据都是采用顺序读取的方式,如果在输入流中某个不需要的数据被读取进来,则只能通过程序将这些数据处理掉,为了解决这样的读取问题,在java中提供了一种回退输入流(PushbackInputStream、PushbackReader),可以把读取进来的某些数据退回到输入流的缓冲区之中。

操作机制:


  

回退操作包括字节流和字符流,这里讲诉字节流。

PushbackInputStream类常用方法:


对于回退操作来说,针对InputStream的三个read()方法,回退流使用了三个unRead()方法,分别与之对应。

范例:在内存中使用ByteArrayInputStream作为输入流 

import java.io.ByteArrayInputStream ;import java.io.PushbackInputStream ;public class PushInputStreamDemo{         publicstatic void main(String args[]) throws Exception {         // 所有异常抛出                   Stringstr = "www.mldnjava.cn" ;             //定义字符串                   PushbackInputStreampush = null ;          // 定义回退流对象                   ByteArrayInputStreambai = null ;            // 定义内存输入流                   bai= new ByteArrayInputStream(str.getBytes()) ; //实例化内存输入流                   push= new PushbackInputStream(bai) ;          //从内存中读取数据                   System.out.print("读取之后的数据为:");                   inttemp = 0 ;                   while((temp=push.read())!=-1){       // 读取内容                            if(temp=='.'){    // 判断是否读取到了“.”                                     push.unread(temp);        // 放回到缓冲区之中                                     temp= push.read() ;        // 再读一遍                                     System.out.print("(退回"+(char)temp+")") ;                            }else{                                     System.out.print((char)temp);        // 输出内容                            }                   }         }}; 

对象序列化

对象序列化就是把对象变为二进制数据流的一种方法,通过对象的序列化可以方便的实现对象的传输或储存。

如果一个类想支持初始化,则该类必须实现java.io.Serilizable接口。该接口定义如下:

publicinterface Serilizable{ }

该接口中不存在方法,因此该类属于一个标示接口,表示实现该的接口的类具备某种能力。

1.      对象的序列化与反序列化


2.      serialVersionUID

在序列化的操作中引入了一个serialVersionUID常量,可以通过此常量来验证版本的一致性,在进行反序列化的时候,JVM会把传进来的字节流中的serialVersionUID与本地对应类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

import java.io.Serializable ;public class Person implementsSerializable{         privateString name ;       // 声明name属性,但是此属性不被序列化         privateint age ;                 // 声明age属性         publicPerson(String name,int age){         // 通过构造设置内容                   this.name= name ;                   this.age= age ;         }         publicString toString(){    // 覆写toString()方法                   return"姓名:" + this.name + ";年龄:" + this.age;         }};

 

3.      对象输出流:ObjectOutputStream


一个对象要想进行输出,就必须使用ObjectOutputStream类,该类定义如下

importjava.io.File ;importjava.io.FileOutputStream ;importjava.io.OutputStream ;importjava.io.ObjectOutputStream ;publicclass SerDemo01{public static void main(String args[]) throwsException {           File f = new File("D:" +File.separator + "test.txt") ;        //定义保存路径           ObjectOutputStream oos = null ;     // 声明对象输出流           OutputStream out = newFileOutputStream(f) ;      // 文件输出流           oos = new ObjectOutputStream(out) ;           oos.writeObject(new Person("张三",30));     // 保存对象           oos.close() ;     // 关闭}};


到底序列化了哪些东西呢?

  所有对象各自拥有各自的属性值,但是所有的方法都是公共的,所以序列化对象的时候实际上序列化的就是属性。

4.      对象输入流:ObjectInputStream


importjava.io.File ;importjava.io.FileInputStream ;importjava.io.InputStream ;importjava.io.ObjectInputStream ;publicclass SerDemo02{public static void main(String args[]) throwsException {           File f = new File("D:" +File.separator + "test.txt") ;        //定义保存路径           ObjectInputStream ois = null ;          // 声明对象输入流           InputStream input = newFileInputStream(f) ;         // 文件输入流           ois = new ObjectInputStream(input) ;     // 实例化对象输入流           Object obj = ois.readObject() ;         // 读取对象           ois.close() ;       // 关闭           System.out.println(obj) ;}};


 

5.      transient关键字

当使用Serializiable接口实现序列化操作的时候,如果一个对象中的某个属性不希望被序列化的话,则可以使用transient关键字进行声明。

import java.io.Serializable ;public class Person implementsSerializable{         privatetransient String name ;        // 声明name属性,但是此属性不被序列化         privateint age ;                 // 声明age属性         publicPerson(String name,int age){         // 通过构造设置内容                   this.name= name ;                   this.age= age ;         }         publicString toString(){    // 覆写toString()方法                   return"姓名:" + this.name + ";年龄:" + this.age;         }}; import java.io.File ;import java.io.IOException ;import java.io.FileOutputStream ;import java.io.OutputStream ;import java.io.ObjectOutputStream ;import java.io.FileInputStream ;import java.io.InputStream ;import java.io.ObjectInputStream ;public class SerDemo04{         publicstatic void main(String args[]) throws Exception{                   ser();                   dser();         }         publicstatic void ser() throws Exception {                   Filef = new File("D:" + File.separator + "test.txt") ;        // 定义保存路径                   ObjectOutputStreamoos = null ;     // 声明对象输出流                   OutputStreamout = new FileOutputStream(f) ;      // 文件输出流                   oos= new ObjectOutputStream(out) ;                   oos.writeObject(newPerson("张三",30)) ;     // 保存对象                   oos.close();     // 关闭         }         publicstatic void dser() throws Exception {                   Filef = new File("D:" + File.separator + "test.txt") ;        // 定义保存路径                   ObjectInputStreamois = null ;          // 声明对象输入流                   InputStreaminput = new FileInputStream(f) ;         //文件输入流                   ois= new ObjectInputStream(input) ;     // 实例化对象输入流                   Objectobj = ois.readObject() ;         // 读取对象                   ois.close();       // 关闭                   System.out.println(obj);         }};


可以看到在反序列化后,打印结果中name为输出null。

 

6.      序列化一组对象

对象输出时只提供了一个对象的输出操作(writeObject(Object obj)),并没有提供多个对象的输出,如果现在要对多个对象进行序列化的操作,则可以使用对象数组完成,由于数组是引用数据类型,所以可以直接使用Object类型进行接收。





importjava.io.File ;importjava.io.IOException ;importjava.io.FileOutputStream ;importjava.io.OutputStream ;importjava.io.ObjectOutputStream ;importjava.io.FileInputStream ;importjava.io.InputStream ;importjava.io.ObjectInputStream ;publicclass SerDemo05{public static void main(String args[]) throwsException{           Person per[] = {new Person("张三",30),newPerson("李四",31),                    new Person("王五",32)};           ser(per) ;           Object o[] = (Object[])dser() ;           for(int i=0;i<o.length;i++){                    Person p = (Person)o[i] ;                    System.out.println(p) ;           }}public static void ser(Object obj[]) throwsException {           File f = new File("D:" +File.separator + "test.txt") ;        //定义保存路径           ObjectOutputStream oos = null ;     // 声明对象输出流           OutputStream out = new FileOutputStream(f);      // 文件输出流           oos = new ObjectOutputStream(out) ;           oos.writeObject(obj) ;      // 保存对象           oos.close() ;     // 关闭}public static Object[] dser() throws Exception{           File f = new File("D:" +File.separator + "test.txt") ;        //定义保存路径           ObjectInputStream ois = null ;          // 声明对象输入流           InputStream input = newFileInputStream(f) ;         // 文件输入流           ois = new ObjectInputStream(input) ;     // 实例化对象输入流           Object obj[] =(Object[])ois.readObject() ;        // 读取对象           ois.close() ;       // 关闭           return obj ;}};

数组能储存的对象数量有限,因此可以使用类集进行序列化的操作。

 

编码设置问题

编码:

        

乱码的产生:

 

 

得到本机的编码显示:

   使用System类获取与本机系统相关的一些信息,使用如下方法

 public static Properties getProperty()

 System.out.println(“系统默认编码” +System.getProperty(“File.encoding”) );

 

范例:

   假设现在本机环境是中文环境,使用的GBK编码,而当前的java程序使用的iso8859-1编码,则需要转码,需要String类的支持。

public byte[] getBytes(String charsetName)throws UnsupportedEncodingException

 可以指定要使用编码

import java.io.OutputStream ;import java.io.FileOutputStream ;import java.io.File ;public class CharSetDemo02{         publicstatic void main(String args[]) throws Exception {                   Filef = new File("D:" + File.separator + "test.txt") ;        // 实例化File类                   OutputStreamout = new FileOutputStream(f) ;      // 实例化输出流                   byteb[] = "中国,你好!".getBytes("ISO8859-1") ;     // 转码操作                   out.write(b);   // 保存                   out.close();      // 关闭         }};

乱码产生的根本原因就是编码的不一致。

 

压缩流

在Java中为了减少传输时的数据量也专门提供了压缩流,可以将文件或者文件夹压缩成ZIP、JAR、GZIP等格式。

该流使用较少,因此只做简要介绍。




0 0
原创粉丝点击