io(六)其他流常用流



1.    打印流:

printStreamFilterOuterputStream的直接子类,FilterOutputStreamOutputStream的直接子类,printStream的构造方法:

PrintStream(File file)                 

PrintStream(OutputStream out)       

PrintStream(String fileName)

printWriterWriter的直接子类,printStream的构造方法:

PrintWriter(File file)

PrintWriter(OutputStream out)

PrintWriter(String fileName)

PrintWriter(Writer out)

打印流的构造方法决定了其技能操作其他输入又能直接操作文件流,当然打印流也能根据指定的编码打印。

打印流中提供了各种打印方法,可以将各种数据类型照原样打印。

import java.io.*;

 

public classPrintWriterDemo {

 

    /**

     * @param args

     * @throws FileNotFoundException

     */

    public static void main(String[]args)  {

        // TODO Auto-generated method stub

       

        BufferedReaderbr = newBufferedReader(newInputStreamReader(System.in));

       

        //打印在控制台上

        //PrintWriter pw = new PrintWriter(newOutputStreamWriter(System.out));

        //PrintWriter pw = new PrintWriter(System.out);

        //打印到文件

        PrintWriterpw = null;

       

        Stringstr = null;

       

        try {

            //打印到文件

            pw = new PrintWriter("D:\\2.txt");

            while((str = br.readLine())!=null){

                if(str.equalsIgnoreCase("exit"))

                     break;

                pw.println(str);

                pw.flush();

            }

        }catch (FileNotFoundExceptione) {

            // TODO Auto-generated catchblock

            e.printStackTrace();

        }catch (IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }finally{

            try {

                if(br !=null)

                 br.close();

            }catch(IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            pw.close();

        }

 

    }

 

}

合并流SequenceInputStream(一个输出流对应多个输入流)是InputStream的直接子类

SequenceInputStream 表示其他输入流的串联,他从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,以此类推直到达到包含的最后一个文件的尾部为止

构造方法:

SequenceInputStream(Enumeration<? extends InputStream>e)  SequenceInputStream(InputStream s1,InputStream s2)

合并流在操作时要用到VectorEnumeration来遍历。

实例:

import java.io.*;

import java.util.*;

public classSequenceInputStreamDemo {

 

    /**

     * @param args

     */

    public static void main(String[] args)throws IOException{

        // TODO Auto-generated method stub

        //定义一个Vector对象用来存放字节输入流

        Vector<InputStream>v = newVector<InputStream>();

        //v中装指定类型的元素

        v.add(new FileInputStream("D:\\count.ini"));

        v.add(new FileInputStream("D:\\2.txt"));

        v.add(new FileInputStream("D:\\count.ini"));

       

        //拿到vEnumeration,以便传给SequenceInputStrem的构造函数

        Enumeration<InputStream>e = v.elements();

       

        //创建一个合并流,必将vectorEnemeration传入

        SequenceInputStreamsis = newSequenceInputStream(e);

       

        //定义一个输出流用来接收合并流中的数据,被将这些数据写入D:\\3.txt

        BufferedWriterbw = newBufferedWriter(newFileWriter("D:\\3.txt"));

         int r = 0;

         while((r = sis.read()) != -1){

             bw.write(r);

         }

       

        sis.close();

        bw.close();

 

    }

 

}

 

切割流:(注意:并没这个类,但我们可以自己实现);

与合并流对应的是切割流(一个输入流对应多个输出流)

例子:切割一个图片后并将其合并

import java.io.*;

import java.util.*;

 

public classSplitFile {

 

    /**

     * @param args

     */

    public static void main(String[] args)throws IOException {

        // TODO Auto-generated method stub

        //splitFile();

        hebing();

    }

   

    //将文件分割

    public static void splitFile()throws IOException{

       

        //建立一个文件输入,并将要被分割的文件作文参数传入

        InputStreamin = newFileInputStream("D:\\0.gif");

       

        //定义一个输出流,用来接收分割后的数据

        FileOutputStreamout= null;

       

       

        //定义一个大小为1M的字节数组,此数组用来分割数组的工具,当此数组装满时,

        //文件就又被分割了1M大小的数据,若最后文件对完了数组未装满,则,将读到的实际长度的字节存入一个独立文件

        byte[] b =new byte[1024*1024];

       

        int len = 0;

        int i = 0;

        while((len = in.read(b)) !=-1){

            //每当数组存满1M时,就创建一个文件,数组中的数据存入此新建文件

            //若最后文件对完了数组未装满,则,将读到的实际长度的字节存入一个此新建文件

            out= newFileOutputStream("D:\\"+ ++i +".part");

            out.write(b,0,len);

            out.close();

        }

       

        in.close();

       

    }

   

    //将分割后的文件合并起来,

    public static void hebing()throws IOException{

       

        //定义一个ArrayList用来存放输入流

        ArrayList<InputStream>al=newArrayList<InputStream>();

        //将要合并的文件出入流中并,将流加入ArrayList中,以便合并流

        for(int i = 1; i < 6 ; i++){

        al.add(new FileInputStream("D:\\"+ i +".part"));

        }

       

      

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

        //因为此处定义了一个局部内部类并且用到了方法中的变量it,所以it必须定义为final的后则不能访问

        //为什么要这样做,因为ArrayList的效率比Vector的效率高

        Enumeration<InputStream> e = new  Enumeration<InputStream>(){

          

        //此处在方法中定义了一个内部类,将ArrayLIstIterator转成Enumeration是为了提高效率

            @Override

            public boolean hasMoreElements() {

                // TODO Auto-generated method stub

                return it.hasNext();

            }

 

            @Override

            public InputStreamnextElement() {

                // TODO Auto-generated method stub

                return it.next();

            }

       

        };

       

        //定义一个合并流,将以上三个流合并

        SequenceInputStream sis = new SequenceInputStream(e);

        //定义一个输出流用来接说合并流的数据,并将数据存入文件,于是被切割的文件就还原了

        FileOutputStream fos = new  FileOutputStream("D:\\1.gif");

        int r = 0;

        while((r = sis.read())!= -1){

        fos.write(r);

        }

       

        sis.close();

        fos.close();

       

    }

 

}

 

 

 

对象的序列化:

ObjectOutputStream--àOutputStream

特有方法(写入对象的方法)writeObject(Object)

ObjectOutputStream(OutputStream out) 

对象想被序列化必须实现一个接口,Serializable接口,(否则报NotSerializableException)此接口中没有定义方法。这样的接口称为标记接口。

反序列化:

ObjectInputStream--àInputStream

ObjectInputStream(InputStream in) 

Object readObject();

类在序列化后,再改变类的源文件,再读是读取不了的,因为读的时候是跟据类文件来读的,类变化后,反序列时Jvm会找不到原有类。其实每个类都有一个UId来区分类的不同的,所以当类以改变,此uid也就改变了。注意Uid是唯一的(改变方法或成员变量Uid都会发生变化)

但是我们可以自己定义一个UId,此时改变类的成员时不会改变这个Uid,所以还是可以反序列化的。

(该字段必须是静态(static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:

例如:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;和面的值可以自己随意赋值。

静态的成员也是不能被序列化的,序列化只是将堆内存中的内容序列化,而静态变量存放在数据区的中,从这里也可以看出来,其实反序列化是根据类来反序列化的

Transient关键字修饰的成员变量,其值在堆内存中存在,而在文件中不存在,所以在反序列化时,Transient关键字修饰的成员变量的值为默认值,(即引用型变量为null,基本输入类型为0或0.0,boolean为false)

管道流:

PipedInputStream----àInputStream

PipedOutputStream---àOutputStream

管道流之间可以直接进行连接,通过结合线程使用

怎么连接呢?

1.  使用构造函数,传入彼此

2.  使用connect方法,输入输出流中都有connect方法

当要从输入流中数据中获得数据时,用输出流中的connect方法,当要从输出流中读数据时,用输入流中的connect方法(构造方法的用法一样)字符的管道流与直接的管道流的操作时一样的

package piped;

 

import java.io.*;

 

public classPipedDemo {

    public static void main(String[] args){

       

        PipedInputStreamin = newPipedInputStream();

        PipedOutputStreamout = newPipedOutputStream();

       

        try {

            in.connect(out);

            /*当要从输入流中数据中获得数据时,用输出流中的connect方法,

             * 当要从输出流中读数据时,用输入流中的connect方法

             * (构造方法的用法一样)字符的管道流与直接的管道流的操作时一样的*/

        }catch(IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

       

        Readr =newRead(in);

        Writew = newWrite(out);

       

        new Thread(r).start();

        new Thread(w).start();

       

       

    }

 

}

 

 

//建立一个线程来从输出流读取数据

class Read implementsRunnable{

     

    PipedInputStreamin ;

    Read(PipedInputStreamin ){

        this.in = in;

    }

    @Override

    public void run() {

        // TODO Auto-generated method stub

        byte[] b =new byte[1024];

        int len = 0;

        try{

            while((len =in.read(b)) != -1){

                System.out.println(new String(b,0,len));

            }

        }catch(IOException e){

            e.printStackTrace();

            throw new RuntimeException("读取失败");

        }finally{

            try {

                if(in !=null)

                in.close();

            }catch(IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    }

 

}

 

//建立一个输出流来往输入流中写入数据

class Write implements Runnable{

    PipedOutputStreamout;

   

    Write(PipedOutputStreamout){

        this.out = out;

    }

    @Override

    public void run() {

        // TODO Auto-generated method stub

        try {

            out.write("ma jing yu I love you I want to fuck you!".getBytes());

        }catch(IOException e) {

            // TODO Auto-generated catch block

            throw new RuntimeException("写入失败");

        }finally{

            try {

                if(out !=null)

                out.close();

            }catch(IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

    }

 

}

可用用于操作基本数据类型的流对象:是流和数据相结合的流;所以他她们的构造函数都要接收一个相应的流对象

DataInputStream -------àFilterInputStream----àInputStream
 

DataInputStream(InputStream in) 

DataOutputStream----àFilterOutputStream---àOutputStream

 DataOutputStream(OutputStream out) 

import java.io.*;

 

public classDataStreamDemo {

 

    /**

     * @param args

     */

    public static void main(String[] args)throws IOException {

        // TODO Auto-generated method stub

        //write() ;

        read();

    }

   

    //将基本数据类型写入文件

    public static void write() throws IOException{

        //定义一个数据输入流,并关联一个文件输出流,准备将基本类型的数据写入文件

        DataOutputStreamdos = newDataOutputStream(newFileOutputStream("D:\\1.txt"));

        //写入Int型数据

        dos.writeInt(4);

        //写入double型数据

        dos.writeDouble(2.345);

        //写入boolean型数据

        dos.writeBoolean(false);

        //写入String型数据,注意如果用WriteUTF方法写入,则必须用ReadUTF读取否则,数据错乱,

        dos.writeUTF("majingyu woxiangcaoni ");

       

        dos.close();

       

    }

   

    //将基本数据类型从文件中读取出来,并且读取顺序要和写入时的一样,即先写Int就先读int

    public static void read() throws IOException{

        //定义一个数据读取流,并接受一个文件输入流,从文件中读取基本数据类型的数据

        DataInputStreamdis = newDataInputStream(newFileInputStream("D:\\1.txt"));

       

        //从文件中读取一个int数据

        int i = dis.readInt();

        sop("i = " + i);

       

        //从文件中读取一个double数据

        double d =dis.readDouble();

        sop("d = "+d);

       

        //从文件中读取一个boolean数据

        boolean b = dis.readBoolean();

        sop("b = " + b);

       

        //readUTF方法从文件中读取一个String数据

        Stringstr = dis.readUTF();

        sop("str::"+ str);

        dis.close();

       

    }

   

    public static void sop(Object o){

        System.out.println(o);

    }

 

}

ByteArrayInputStream-------àInputStream 在构造时,需要接受数据源。而且数据源是一个字节数组

ByteArrayInputStream(byte[] buf) 

ByteArrayInputStream(byte[] buf,int offset,int length)

 

 

 

ByteArrayOutputStream------àOutputStream:在构造时,不用定义数据的目的地,因为该对象中已经封装了一个可变长度的字节数组 :这就是数据目的地,

ByteArrayOutputStream(int size) 

ByteArrayOutputStream(){

由于这两个流对象造作的都是数组,并没有操作系统资源。所以不用进行关闭,即使关闭了,流还是可以使用。也不会产生任何的IO异常。

只有一个方法会抛异常:writeTo(OutputStream os);将字节数组输出流中的可变长度数组的内容,写入指定的输出流。

特有方法:size();获得可变长度字节数组的长度。没有写入数据时是0;

toString()方法是可变长度字节数组转成String。

import java.io.*;

 

public classByteArrayDemo {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        method_1();

        method_2();

    }

 

    //字节数组输出流的方法的用法

    public static void method_1(){

        ByteArrayOutputStreambaos = newByteArrayOutputStream();

       

        //获取字节输出流中可变长度的数组的大小,在未往里写数据之前,为0

        sop(baos.size());

        try {

            baos.write("liaoli".getBytes());

        }catch(IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        //获取字节输出流中可变长度的数组的大小,在未往里写数据之前,为0,写入数据后为写入的字节数

        int i = baos.size();

       

        //字节数组输出流,中定义了将可变长度的字符数组转成String的方法toString()方法

        Stringstr = baos.toString();

        sop(i);

        sop(str);

        try {

            //将字节数组输出流中的可变长度数组的内容,写入指定的输出流。

            baos.writeTo(new FileOutputStream("D:\\1.txt"));

        }catch(FileNotFoundException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }catch(IOException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }finally{

            try {

                if(baos !=null)

                baos.close();

            }catch(IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

       

    }

   

    public static void method_2(){

      //定义了一个字节数组输入流。并传入一个字节数组,作为数据源

        ByteArrayInputStreambais = newByteArrayInputStream("majingyuiloveyou".getBytes());

       

        //定义了一个字节数组输出流,用来接收从字节数组输入流中读取的数据,将接收的数据存入字节数组输出流的可变长度数组中

        ByteArrayOutputStreambaos = newByteArrayOutputStream();

       

        //获取字节输出流中可变长度的数组的大小,在未往里写数据之前,为0

        sop(baos.size());

       

        int i = 0;

       

        //从字节数组输出流中读取数据,并将读取的数据存入字节输出流中的可变长度的字节数组中

        while((i = bais.read())!=-1){

            baos.write(i);

        }

        //获取字节输出流中可变长度的数组的大小,在未往里写数据之前,为0,写入数据后为写入的字节数

        sop(baos.size());

        sop(baos.toString());

    }

   

   

    public static void sop(Object o){

        System.out.println(o);

    }

}

 

 

 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值