java中级-9-IO流知识点串讲(3)-IO修饰(功能扩展)类及其应用


------- android培训java培训、期待与您交流! ----------



        在字符流、字节流之下,java.io包下,还有其他几种基于这两种流为基础的新生类型。打印流PrintWriter、PrintStream,序列流SequenceInputStream,操作对象流ObjectInputStream、ObjectOutputStream。这些流,即可以看作是原有字节字符流的功能专精的强化版,也可以认为是单独衍生出来的新类型。

 

PrintWriter与PrintStream

        这两个类的作用相仿,但是PrintWriter着重从字符流的角度来操纵输入流,另一个PrintStream则是直接从字节来实现的。PrintWriter的构造函数中,可以用OutputStream及其子类来作为初始化操作赋值。这两个类都是原类的修饰类,提供了打印print、println方法,并继承了父类的write方法,他们的write都具有父类的特征,即写入数据类型与父类保持一致。因此,相较而言字符更贴近通常操作,PrintWriter更常用一些。唯一一点不便的是,使用PrintWriter类,每次输入都需要flush刷新,而PrintStream类则不需要。

         我们来看一个对Properties类与PrintWriter类等I/O类的综合运用例题:

/**@author:LZ
*/
/*目标:读取当前目录下的config.ini文件,并对其中的参数进行修改或创建
  要求:1 对其中的参数进行修改或创建
              2 对配置文件进行备份,并将备份文件建立在当前目录下,命名为backup.ini
  思路:1 读取配置文件,没有则创建
              2 判断是否修改或添加,并进行相关操作
              3 备份配置文件
*/
import java.io.*;
class  CreateConfigDocTest
{
       public static void main(String[] args)
       {
              Properties p =new Properties();
              File config = newFile("config.ini");
             
              p = loadProp(config); //载入原有config.ini默认设定,如没有则创建
              changeProp(config);        //判断是否需要对面参数进行修改
              back(p);                  //实现配置文件备份,如没有则创建
 
       }
 
       public static Properties loadProp(Fileconfig)
       {
              if (!config.exists())
                     config.createNewFile();
              FileInputStream br = newFileInputStream(config);  //连接配置文件
                           
              Properties p = new Properties();
              p.load(br);
              p.list(System.out);   //输出读取到的配置情况
 
              br.close();
              return p;
       }
 
       public static void changeProp(Propertiesp)
       {
              BufferedReader in =
                     new BufferedReader(newInputStreamReader(System.in);
 
              String a = null
              while(!(a=in.readLine()).equals("end")) 
              {
                     sop(a+"_search_result:"+p.getProprity(a));
                     sop("change?(y\\n)");
                     if(in.readLine()=="y")                  //判断更改配置与否
                            p.setProperty(a,in.readLine());  //读取相应配置值,赋值
              }
 
              in.close();
       }
 
       public static void backup(Properties p)
       {
              File back = newFile("backup.ini");
              if (!back.exists())
                     back.createNewFile();
              PrintWriter pw = newPrintWriter(back); //连接备份文件
 
              p.list(back); // Properties的list方法参数为PrintWriter或者PrintStream类型
                              //也可以,或者建议使用store( OutputStream o,String c)方法
              pw.close();
       }
 
       public static void sop(Object obj)
       {
              System.out.println(obj);
       }
}

        上面的例题展现了配置文件、配置类Properties非临时性配置形式的基本应用,不难看出,如果想要存储相应的配置信息,我们所涉及的I/O操作就肯定会比较多。其中的一些操作,如PrintWriter类对象给list函数参数赋值等,就使得程序在I/O部分的代码可读性提高。

 

SequenceInputeStream序列输入流

        SequenceInputStream类为InputStream类的子类,能够将多个输入流整合为一个输入流,继承了父类方法。该类的主要不同,就在于它的构造函数实现了多个字节输入流串联,对应的构造函数SequenceInputStream(Enumeration e)。

        序列流只有输入流,无输出流。下面的使用案例中,我们用序列流来简称序列输入流:

import java.io.*;
import java.util.*;
class  SequenceISTest
{
       public static void main(String[] args)
       {
              Vector<FileInputStream> v =new Vector<FileInputStream>(); //建立输出流集合
 
              v.add(newFileInputStream("1.txt"));
              v.add(newFileInputStream("2.txt"));
              v.add(newFileInputStream("3.txt"));
 
              Enumeration<FileInputStream>e = v.elements();  //建立输出流对应枚举类
             
              SequenceInputStream si = newSequenceInputStream(e); //关联枚举类到序列流
 
              byte[] b = new byte[1024];
              int num = 0;
              while ((num=si.read(b))!=-1)
              {
                     System.out.write(b,0,num);//将合并后的文档内容输出到控制台
              }
             
              si.close(); //关闭序列流
       }
}

         相比起数据的合流,分割操作就需要通过对字节流的基本操作来实现了。我们的思想是通过输出流的write方法,和输入流的read方法,将读到的数据通过我们给定的暂存,存放到一定大小的不同文件当中,来完成文件及数据的分割。如下所示:

/**@author:LZ
*/
/*目标:实现对本Java程序文档的拆分,和重组操作
  要求:1 能够实现对本程序的拆分,按照2Mb的准则进行
              2 给予用户重组文档选项,并按用户要求命名保存
  思路:1 初始化变量,建立表List,便于恢复
              2 拆分文件为为2Mb大小的碎片文件,后缀为".p"
              3 按要求,如要恢复则在用户指定位置存储
*/
import java.io.*;
import java.util.*;
class Split_MergeTest
{
       public static void main(String[]args)  //程序主函数
       {
              //定义需要拆分的文档,完成控制台读取流初始化
              File fs = newFile("Split_MergeTest.java");
              BufferedReader br =
                     new BufferedReader(newInputStreamReader(System.in)); 
             
              ArrayList a = null;
 
 
              //执行拆分操作
              a = split(fs);
              sop("done!!\nDo you want tomerge the pack?(y/n)");
              String c = null;
             
              //判断是否需要执行拆分后碎片文档的合并操作
              if((c=br.readLine()).equals("y"))
              {
                     merge(a,newFile(br.readLine()));
                     sop("mergedone!!");
              }
              else if(c.equals("no"))
                     sop("done!!");
              else
                     sop("error: wronginput!");
             
              //关闭控制台读取流
              br.close();
       }
 
       //拆分函数,参数为需要拆分文档
       public staticArrayList<FileInputStream> split(File f) 
       {
              FileInputStream in = newFileInputStream(f);
              FileOutputStream out = null;
 
              ArrayList<FileInputStream>res = new ArrayList<FileInputStream>();
 
              byte[] b = new byte[1024*1024*2];
              int num = 0;
              for (int i=0;(num=in.read(b))!=-1; i++)
              {
                     out = newFileOutputStream(i+".p");
                     out.write(b,0,num);
                     res.add(out);  //将划分文件添加到结果集中
                     out.close();
                     sop("split to part"+i+" !");
              }
 
              in.close();
              return res;
       }
 
       //合并操作,参数a为
       public static void merge(ArrayList<?extends InputStream> a, File f)
       {
              Iterator ite = a.iterator();
              Enumeration e = new Enumeration()  //枚举类,自定义覆盖原方法
              {
                     public booleanhadMoreElements()
                     {
                            returnite.hasNext();
                     }
                     public booleannextElement()
                     {
                            return ite.next();
                     }
              }
 
              SequenceInputStream sin = newSequenceInputStream(e);
              FileOutputStream out = newFileOutputStream(f);
             
              byte[] b = new byte[1024]
              int num = 0;
              while ((num=sin.read(b))!=-1)
              {
                     out.write(b,0,num);
              }
             
              out.close();
              sin.close();
             
       }
 
       public static void sop(Object obj)
       {
              System.out.println(obj);
       }
}

         当然,在文件的分割上,我们可以通过固定的暂存与计数器配合的方式,来实现人为可定的分割大小。计数器来计量每个包大小,当达到一定程度的时候,就重新定义一个新的分割包,来装载剩余文件。

 


------- android培训java培训、期待与您交流! ----------


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值