序列流与编码转换

来源:互联网 发布:血战到底麻将算法 编辑:程序博客网 时间:2024/06/08 19:45
序列流:

      序列流(SequenceInputStream)也称合并流,常用于多个文件的合并。它的原理就是将每一个读取流对象存储到一个集合中。最后一个流对象的结尾就是这个流的结尾。

      构造方法是:

                 SequenceInputStream(InputStream in A,InputStream in B);//将A、B两个输入流对象合并到一起。

                 SequenceInputStream(Enumeration<? extends InputStream> en);//多个输入流的合并方法。

提到序列流就必须提到它的public int available()方法,其作用是返回不受阻塞的从当前底层输入流读取或跳过字节数的估计值,如果该输入流已关闭,则返回0。

多个文件合并的方法:

SequenceInputStream(Enumeration<? extends InputStream>e) 是通过记住参数来初始化新创建的序列流(SequenceInputStream),且该参数必须是生成(Enumeration)枚举类型的参数。按顺序读取由该枚举生成的字节流,以提供从此序列流(SequenceInputStream)读取的字节,在把枚举中的输入流用完之后,将调用该流的close方法将其关闭。

Enumeration中的唯一一个boolean方法hasMoreElements(),其作用是测试此枚举是否包含更多的元素。当该枚举对象中含元素时,返回值是:“true”,否则返回“false”。

E nextElement()返回枚举的下一个元素,若没有更多的元素存在,就抛出:NoSuchElementException;

因为Enumeration是Vector中特有的取出方式。而Vector被ArrayList取代。可是ArrayList相对来说效率比较低,因此就要找一种可以替代Enumeration的方法。于是就用到了迭代器(Iterator)。           public interface Iterator<E>,它是对collection进行迭代的迭代器。取代了Java Collection Framework。从一定程度上讲,迭代器与枚举还是有些不同的:首先,迭代器允许调用者利用定义良好的语义从迭代器指向的collection中移除元素;其次,方法名称有了改进,利于人们理解。

迭代器中的调用方法有三种:hasNext(),next()和remove()。其中,hasNext()方法、next()方法与Enumeraion中的hasMoreElements()、nextElement()方法产生的效果一样,这里就不在重复了。然后是remove(),它的作用是:从迭代器指向的collection中移除迭代器返回的最后一个元素,每次next只能调用一次此方法。它是一个可选操作,可是,如果进行迭代是使用了其他方式修改了collection,或者上次的next()方法之后已经调用了remove方法,那么迭代器会抛出异常。

下面是一个合并文件的小段代码:

             ArrayList<FileInputStream > al = new ArrayList<FileInputStream>();

 

              for(int x=1; x<4; x++)

              al.add(new FileInputStream(x+".txt"));

      

//返回按适当顺序在列表的元素上进行迭代的迭代器。

       final Iterator<FileInputStream> it = al.iterator();

       Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()      {

              public boolean hasMoreElements()              {

                     return it.hasNext();

              }

              public FileInputStream nextElement()          {

                     return it.next();

              }

       };

             

       //多个流就变成了一个流,这就是数据源。

       SequenceInputStream sis = new SequenceInputStream(en);

      

       //创建数据目的。

       FileOutputStream fos = new FileOutputStream("4.txt");

 

       byte[] buf = new byte[1024*4];

      

       int len = 0;

 

       while((len=sis.read(buf))!=-1)

       {

              fos.write(buf,0,len);

       }

 

       fos.close();

sis.close();

说了合并,接下来就要说一下分割,分割就是建立一个有一定大小的缓冲流。因为缓冲过程就是把读入的数据流先暂时存放在缓冲流中,等缓冲流的空间装满以后,再一起流出,写入要存放的文件中。所以,它就是把一个缓冲流中的东西放置在一个文件或内存中,这样一一对应,分割完成。

下面是一个分割的实例:

      一个读取对应多了输出。

       FileInputStream fis = new FileInputStream("1.mp3");

 

       FileOutputStream fos  = null;

 

       byte[] buf = new byte[1024*1024];//是一个1m的缓冲区。

 

       int len = 0;

       int count = 1;

 

       while((len=fis.read(buf))!=-1)

       {

              fos = new FileOutputStream((count++)+".mp3");

              fos.write(buf,0,len);

 

              fos.close();

       }

       fis.close();

 

       //这样就是将1.mp3文件切割成多个碎片文件。

编码转换:

      编码转换过程:

            字符串     -->字节数组  :通过getBytes(charset)方法进行编码。

            字节数组-->字符串 :通过String(byte[],charset)方法进行解码。

////////注意编码和解码必须一样,否则会导致文件不可用。如果编码错误,没有返回方式;但是如果解码错误,可以进行再次编译。就是把错误解码得到的文件用编码的方式进行编译(此时的编码就是错误得编码),然后在用正确的解码进行解析。

      以下是常用的编码表:

       ascii:美国标准信息交换码。使用的是1个字节的7位来表示该表中的字符。

      ISO8859-1:拉丁码表。使用1个字节来表示。

      GB2312:简体中文码表。

      GBK:简体中文码表,比GB2312融入更多的中文文件和符号。

      unicode:国际标准码表。都用两个字节表示一个字符。

      UTF-8:对unicode进行优化,每一个字节都加入了标识头。

编码错误后的解码方式:

      String s = "你好";

       // 编码。

       byte[] b = s.getBytes("GBK");

      String s1 = new String(b, "iso8859-1");

      

    //解码

System.out.println(s1);// ????

 

       // 想要还原。

       /*

        * 对s1先进行一次解码码表的编码。获取原字节数据。 然后在对原字节数据进行指定编码表的解码。

        */

       byte[] b1 = s1.getBytes("iso8859-1");

       System.out.println(new String(b1, "GBK"));

    }

 

原创粉丝点击