Java 基础 IO(三)

本文深入探讨Java IO流中的回退流概念及其应用,并详细介绍了对象序列化的基本原理、实现方式以及序列化过程中的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java IO(三)

 -----------------------------

回退流

给用户第二次读的机会。在JAVA IO中所有的数据都是采用顺序的读取方式,即,对于一个输入流来讲都是采用从头到尾顺序读取,如果在输入流中某个不需要的内容被读取进来,则只能通过程序将这些不需要的内容处理掉,为了解决这样的读取问题,在JAVA中提供了一种回退输入流(PushbackInputStream、PushbackReader),可以把读取进来的某些数据重新退回到输入流的缓冲区之中。

对于回退操作来说,提供了三个unread()的操作方法,这三个操作方法与InputStream类中的read()方法是一一对应的。

实例:把内容设置到内存中

importjava.io.ByteArrayInputStream ;
importjava.io.PushbackInputStream ;
publicclass PushInputStreamDemo{
       public static void main(String args[])throws Exception {   // 所有异常抛出
              String str = "www.hmjava.cn";           // 定义字符串
              PushbackInputStreampush = null ;             // 定义回退流对象
              ByteArrayInputStream bai = null ;              // 定义内存输入流
              bai = newByteArrayInputStream(str.getBytes()) ;       //实例化内存输入流
              push = newPushbackInputStream(bai) ;      // 从内存中读取数据
              System.out.print("读取之后的数据为:") ;
              int temp = 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程序的开发中最常见的是以下几种编码:ISO8859-1、GBK/GB2312、unicode、UTF编码。

ISO8859-1编码属于单字节编码,最多只能表示0~255的字符范围,主要在英文上应用。

GBK/GB2312:中文的国际编码,专门用来表示汉字,是双字节编码。

unicode:JAVA中就是使用此编码方式,也是最标准的一种编码,是使用16进制表示的编码。但此编码不兼容ISO8859-1编码。

UTF:由于unicode不支持ISO8859-1编码,因此产生了UTF编码,UTF编码兼容了ISO8859-1编码,同时也可以用来表示所有的语言字符,一般在中文网页中使用此编码。

乱码的产生

如果本机的默认编码是GBK,但是在程序中使用了ISO8859-1编码,则就会出现字符乱码问题。

利用System类来得到当前系统的有关信息,也可以直接使用此类来找到系统的默认编码。

       public sstatic Properties getProperty()

实例:

publicclass CharSetDemo01{
       public static void main(String args[]){
              System.out.println("系统默认编码:" +
                     System.getProperty("file.encoding")); // 获取当前系统编码
       }
};

乱码问题实例:

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

对象序列化

掌握对象序列化的作用

掌握Serializable接口的作用

可以使用ObjectOutputStream进行对象序列化操作

可以使用ObjectInputSTream进行对象反序列化操作

掌握Externalizable接口的作用及与Serializable接口的实现区别

掌握transient关键字的作用

序列化一组对象

对象序列化:一个对象产生之后实际上是在内存中为其开辟了一个存储空间,方便存储信息。

对象序列化与反序列化:

想要完成对象的输入输出,还必须依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)

使用对象输出流输出序死化对象的步骤,有时也称为列化,而使用对象输入流读入对象的过程,有时也称为反序列化。

序列化操作(ObjectOutputStream)实例:

importjava.io.File ;
importjava.io.FileOutputStream ;
importjava.io.OutputStream ;
importjava.io.ObjectOutputStream ;
publicclass SerDemo01{
       public static void main(String args[])throws Exception {
              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() ;    // 关闭
       }
};

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

反序列化操作(ObjectInputStream)实例:

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

Externalizable接口

使用Serilizable接口可以方便的序列化一个对象,但是在序列化操作中也提供了另外一种序列化机制——Externalizable接口。

利用此接口修改前面的程序:

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 SerDemo04{
       public static void main(String args[])throws Exception{
              ser() ;
              dser() ;
       }
       public static void ser() throws Exception{
              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() ;    // 关闭
       }
       public static void 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 = ois.readObject() ;      // 读取对象
              ois.close() ;     // 关闭
              System.out.println(obj) ;
       }
};

在开发中使用Serializable接口是最多的,而Externalizable接口基本上是不会出现的。

transient关键字

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

序列化一组对象

如果要保存一组对象,则最好使用对象数组的形式完成。

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[])throws Exception{
              Person per[] = {new Person("张三",30),new Person("李四",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[])throws Exception {
              File f = new File("D:" +File.separator + "test.txt") ;  //定义保存路径
              ObjectOutputStream oos = null ;   // 声明对象输出流
              OutputStream out = newFileOutputStream(f) ;   // 文件输出流
              oos = new ObjectOutputStream(out);
              oos.writeObject(obj) ;    // 保存对象
              oos.close() ;    // 关闭
       }
       public static Object[] dser() throwsException {
              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 ;
       }
};

---------------------------------------------------------------------------------------------

实例操作:单人信息管理程序

实例要求:

将之前的菜单程序进行扩充,要求:增加的时候可以增加一个人的完整信息,人的信息包括年龄和姓名。保存之后也可以修改此信息,删除此信息,查询此信息。

提示:使用对象序列化保存

此时程序可以使用之前讲解过的几个类:InputData、Person、Operate、Menu。

文件操作类实现:

importjava.io.File ;
importjava.io.FileInputStream ;
importjava.io.FileOutputStream ;
importjava.io.ObjectInputStream ;
importjava.io.ObjectOutputStream ;
publicclass FileOperate{       // 此类专门用于保存和读取
       private File file = null ;  // 定义文件对象
       public FileOperate(String pathName){  // 通过   构造传递文件路径
              this.file = new File(pathName) ;
       }
       public boolean save(Object obj) throwsException{     // 保存对象
              ObjectOutputStream oos = null ;          // 对象输出流
              boolean flag = false ;     // 定义操作标志位
              try{
                     oos = newObjectOutputStream(new FileOutputStream(this.file)) ;    // 实例化对象输出流
                     oos.writeObject(obj) ;    // 写入对象
                     flag = true ;
              }catch(Exception e){
                     throw e ; // 有异常交给被调用处处理
              }finally{
                     if(oos!=null){
                            oos.close() ;
                     }
              }
              return flag ;
       }
       public Object load() throws Exception{       // 读取对象
              Object obj = null ;  // 接收读取的内容
              ObjectInputStream ois = null ;     
              try{
                     ois = new ObjectInputStream(newFileInputStream(this.file)) ;  // 实例化对象输入流
                     obj = ois.readObject() ;  // 读取对象
              }catch(Exception e){
                     throw e ;
              }finally{
                     if(ois!=null){
                            ois.close() ;     // 关闭
                     }
              }
              return obj ;
       }
};

Person类:

importjava.io.Serializable ;
publicclass Person implements Serializable{
       private String name ;            // 定义name属性
       private int age ;                    // 定义age属性
       public Person(String name,int age){
              this.name = name;
              this.age = age ;
       }
       public String toString(){
              return "姓名:" + this.name + ";年龄:" + this.age ;
       }
       public void setName(String name){
              this.name = name ;
       }
       public void setAge(int age){
              this.age = age ;
       }
       public String getName(){
              return this.name ;
       }
       public int getAge(){
              return this.age ;
       }
};

修改操作类:

publicclass Operate{
       public static void add(){ // 增加操作
              InputData input = new InputData();            // 实例化输入数据对象
              FileOperate fo = newFileOperate("d:\\test.per") ;
              String name =input.getString("请输入姓名:") ;
              int age = input.getInt("请输入年龄:" , "年龄必须是数字!") ;
              Person per = new Person(name,age);   // 实例化Person对象
              try{
                     fo.save(per) ;  // 保存对象
              }catch(Exception e){
                     e.printStackTrace() ;
              }
              System.out.println("信息增加成功!") ;
       }
       public static void delete(){    // 删除操作
              FileOperate fo = newFileOperate("d:\\test.per") ;
              try{
                     fo.save(null) ; // 保存对象
              }catch(Exception e){
                     e.printStackTrace() ;
              }
              System.out.println("信息删除成功!") ;
       }
       public static void update(){   // 更新操作
              InputData input = new InputData();            // 实例化输入数据对象
              FileOperate fo = newFileOperate("d:\\test.per") ;
              Person per = null ;
              try{
                     per = (Person)fo.load() ;       // 读取对象
              }catch(Exception e){
                     e.printStackTrace() ;
              }
              String name =input.getString("请输入姓名(原姓名:"+per.getName()+"):") ;
              int age = input.getInt("请输入年龄(原年龄:"+per.getAge()+"):" , "年龄必须是数字!") ;
              per = new Person(name,age) ;       // 实例化Person对象
              try{
                     fo.save(per) ;  // 保存对象
              }catch(Exception e){
                     e.printStackTrace() ;
              }
              System.out.println("信息修改成功!") ;
       }
       public static void find(){       // 查看操作
              FileOperate fo = newFileOperate("d:\\test.per") ;
              Person per = null ;
              try{
                     per = (Person)fo.load() ;       // 读取对象
              }catch(Exception e){
                     e.printStackTrace() ;
              }
              System.out.println(per) ;
       }
};

菜单类:

publicclass Menu{
       public Menu(){
              while(true){
                     this.show() ;          // 无限制调用菜单的显示
              }
       }
       public void show(){
              System.out.println("===== Xxx系统 =====") ;
              System.out.println("    [1]、增加数据");
              System.out.println("    [2]、删除数据");
              System.out.println("    [3]、修改数据");
              System.out.println("    [4]、查看数据");
              System.out.println("    [0]、系统退出\n");
              InputData input = new InputData();
              int i = input.getInt("请选择:","请输入正确的选项!") ;
              switch(i){
                     case 1:{
                            Operate.add() ;              // 调用增加操作
                            break ;
                     }
                     case 2:{
                            Operate.delete() ;   // 调用删除操作
                            break ;
                     }
                     case 3:{
                            Operate.update() ;  // 调用更新操作
                            break ;
                     }
                     case 4:{
                            Operate.find() ;             // 调用查看操作
                            break ;
                     }
                     case 0:{
                            System.exit(1) ;            // 系统退出
                            break ;
                     }
                     default:{
                            System.out.println("请选择正确的操作!") ;
                     }
              }
       }
};

主类(测试类):

importjava.io.* ;
publicclass ExecDemo03{
       public static void main(String args[])throws Exception{
              new Menu() ;
       }
};

--------------------------------------------------------

实例操作:投票程序

实例要求:

有一个班采用民主投票的方法推选班长,班长候选人共4位,每个人姓名及代号分别为1、张三 2、李四3、王五 4、赵六。程序操作员将每张选票上所填的代号(1、2、3、4)循环输入电脑,输入数字0结束输入,然后将所有候选人的得票情况显示出来,并显示最终当选者信息。

提示:利用Comparable比较器、Arras类、对象数组实现

学生类实现:

publicclass Student implements Comparable<Student>{
       private int stuNo ;  // 学生编号
       private String name ;     // 学生姓名
       private int vote ;     // 学生票数
       public Student(int stuNo,String name,intvote){
              this.setStuNo(stuNo) ;
              this.setName(name) ;
              this.setVote(vote) ;
       }
       public int compareTo(Student o){
              if(this.vote<o.vote){
                     return 1 ;
              }else if(this.vote>o.vote){
                     return -1 ;
              }else{
                     return 0 ;
              }
       }
       public void setStuNo(int stuNo){
              this.stuNo = stuNo ;
       }
       public void setName(String name){
              this.name = name ;
       }
       public void setVote(int vote){
              this.vote = vote ;
       }
       public int getStuNo(){
              return this.stuNo ;
       }
       public String getName(){
              return this.name ;
       }
       public int getVote(){
              return this.vote ;
       }
 };

InputData类实现;

importjava.io.BufferedReader ;
importjava.io.InputStreamReader ;
importjava.io.IOException ;
publicclass InputData{
       private BufferedReader buf = null ;             // 接收数据
       public InputData(){
              this.buf = new BufferedReader(newInputStreamReader(System.in)) ;
       }
       public String getString(String info){    // 得到字符串
              String temp =  null ;    //接收输入内容
              System.out.print(info) ;
              try{
                     temp = this.buf.readLine();   // 接收数据
              }catch(IOException e){
                     e.printStackTrace() ;
              }
              return temp ;
       }
       public int getInt(String info,Stringerr){      // 得到整型数据
              int temp = 0 ;
              String str = null ;
              boolean flag = true ;      // 定义一个循环标记
              while(flag){
                     str = this.getString(info);
                     if(str.matches("\\d+")){
                            temp =Integer.parseInt(str) ;
                            flag = false ;   // 更改标志位,将退出循环
                     }else{
                            System.out.println(err);
                     }
              }
              return temp ;
       }
};

操作类实现:

publicclass Operate{
       private Student stu[] = {newStudent(1,"张三",0),new Student(2,"李四",0),
              new Student(3,"王五",0),new Student(4,"赵六",0)} ;// 侯选人信息
       private boolean flag = true ;
       public Operate(){
              this.printInfo() ;     // 先输出候选人信息
              while(flag){
                     this.vote() ;     // 循环调用投票
              }
              this.printInfo() ;     // 输出投票之后的侯选人信息
              this.getResult() ;     // 得到结果
       }
       private void getResult(){       // 得到最终的投票结果
              java.util.Arrays.sort(this.stu) ;      // 排序
              System.out.println("投票最终结果:" + this.stu[0].getName()+"同学,最后以"+this.stu[0].getVote()+"票当选班长!") ;
       }
       public void vote(){ // 此方法完成投票功能
              InputData input = new InputData();     // 输入数据
              int num = input.getInt("请输入班长侯选人代号(数字0结束):","此选票无效,请输入正确的侯选人代号!") ;
              switch(num){
                     case 0:{
                            this.flag = false ;    // 中断循环
                            break ;
                     }
                     case 1:{
                            this.stu[0].setVote(this.stu[0].getVote()+ 1) ;
                            break ;
                     }
                     case 2:{
                            this.stu[1].setVote(this.stu[1].getVote()+ 1) ;
                            break ;
                     }
                     case 3:{
                            this.stu[2].setVote(this.stu[2].getVote()+ 1) ;
                            break ;
                     }
                     case 4:{
                            this.stu[3].setVote(this.stu[3].getVote()+ 1) ;
                            break ;
                     }
                     default:{
                            System.out.println("此选票无效,请输入正确的候选人代号!") ;
                     }
              }
       }
       public void printInfo(){
              for(int i=0;i<stu.length;i++){
                     System.out.println(this.stu[i].getStuNo()+ ":"
                            +this.stu[i].getName() + "【"+this.stu[i].getVote()+"】") ;      
              }
       }
};

主类:

publicclass ExecDemo{
       public static void main(String args[]){
              new Operate() ;
       }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值