java io包字节流类图详解

来源:互联网 发布:java工程师工作规划 编辑:程序博客网 时间:2024/06/18 10:08

在学长的要求下,我作为刚进入IT界不到两个月的小白鼠,利用了两天时间制作了一份关于java io包的字节流的ppt,并决定将其写成自己的第一篇博客。大牛看到本文槽点望请及时与作者联系,新人入门不喜勿喷,谢谢。

首先我们来看一看io包中的字节流类库图。

本文将按着接口,InputStream类,OutputStream类,子类实例的顺序进行讲解。

一 、包中接口

ObjectInput接口:ObjectInput 扩展 DataInput 接口以包含对象的读操作。DataInput 包括基本类型的输入方法;ObjectInput 扩展了该接口,以包含对象、数组和 String 的输出方法。其子接口有:
InputStream
ObjectOutputStream
ObjectInputStream

DataInput接口:用于从二进制流中读取字节,并根据所有 Java 基本类型数据进行重构。同时还提供根据 UTF-8 修改版格式的数据重构 String 的工具。后文出现的实现类有:
DataInputStream
ObjectInputStream

DataOutput 接口:用于将数据从任意 Java 基本类型转换为一系列字节,并将这些字节写入二进制流。同时还提供了一个将 String 转换成 UTF-8 修改版格式并写入所得到的系列字节的工具。后文出现的DataOutput 接口的实现类有:
ObjectOutputStream
DataOutputStream
RandomAccessFile

ObjectOutput 接口:扩展 DataOutput 接口以包含对象的写入操作。DataOutput 包括基本类型的输出方法;ObjectOutput 扩展了该接口,以包含对象、数组和 String 的输出方法。后文出现的ObjectOutput接口实现类有:
ObjectOutputStream

二、InputStream及其子类

此抽象类是表示字节输入流的所有类的超类,继承该类的子类能够实现对数据的读取 。InputStream的作用是用来表示那些从不同数据源产生输入的类。
InputStream读取数据源及其对应子类:

1)字节数组 – ByteArrayInputStream

2)String对象 – StringBufferInputStream

3)文件 – FileInputStream

4)“管道”:从一端输入,从另一端输出 – PipedInputStream

5)一个由其他种类的流组成的序列 – ObjectInputStream

6)其他数据源,如音频文件 – AudioInputStream

三、OutputStream及其子类

OutputStream类别的类决定了输出所要去的目标,这些目标包括及其对应子类:

1)字节数组 – ByteArrayOutputStream

2)文件 – FileOutputStream

3)“管道” – PipedOutputStream

四、应用子类实例

  1. 读取音频文件的AudioInputStream
    需求说明:现在我们要用AudioInputStream 读取C:\Users\lenovo\Music目录下的音频文件”逃跑计划 - 夜空中最亮的星.wav“。
File f = new File("C:\\Users\\lenovo\\Music\\逃跑计划 - 夜空中最亮的星.wav");        byte[] b = new byte[1024];        try(AudioInputStream as = AudioSystem.getAudioInputStream(f);){            //将音频文件读取字节数组中            as.read(b);        } catch (Exception e) {            e.printStackTrace();        }        System.out.println(b[0]);

注意:AudioInputStream读取的音频文件必须是wav格式的。
备注:本文为了验证成功读取文件使用System.out.println(b[0])查看b中的数据。

2.读取字节数组的ByteArrayInputStream
需求说明:现在我们要用ByteArrayInputStream 读取”F:\1.txt文件”。

    byte buf[] = new byte[1024];    byte b[] = new byte[1024];    // 创建一个 ByteArrayInputStream,使用 b作为其缓冲区数组。    try(InputStream is = new FileInputStream("C:/Users/lenovo/Music/Justin Bieber - Love Yourself.mp3");    ByteArrayInputStream bais = new ByteArrayInputStream(b);)    {        is.read(b);        //将数据此输入流读入 byte数组        bais.read(buf);    } catch (Exception e) {        e.printStackTrace();    }    System.out.println(buf[0]);

3.写入字节的ByteArrayOutputStream
需求说明:现在我们要用ByteArrayOutputStream 接收输入流中的数据,然后将数据写入字节数组。

    int temp = 0;    //创建输入输出流对象    try(InputStream is = new FileInputStream("C:/Users/lenovo/Music/Justin Bieber - Love Yourself.mp3");        ByteArrayOutputStream baos = new ByteArrayOutputStream())    {        //将输入流中的数据写入输出流        while((temp=is.read())!=-1){            baos.write(temp);        }        //将输出流中的数据导出到字节数组中        byte[] b = baos.toByteArray();        System.out.println(b[0]);    } catch (Exception e) {        e.printStackTrace();}

4.读取文件的FileInputStream
需求说明:现在我们要用FileInputStream 将文件中的数据读入字节数组。

byte[] b = new byte[1024];try(InputStream is = new FileInputStream("F:/1.txt")){    //将文件中的数据读入字节数组    is.read(b);     } catch (Exception e) {        e.printStackTrace();    }    System.out.println(b[0]);

5.将数据写入文件的FileOutputStream
需求说明:将”1.txt“文件复制到一个指定路径的新文件”2.txt“中。

    int temp = 0;    //创建文件读取输出流    try(InputStream is = new FileInputStream("F:/1.txt");        FileOutputStream fos = new FileOutputStream("F:/3.txt"))    {        while((temp=is.read())!=-1){            fos.write(temp);            }    } catch (Exception e) {        e.printStackTrace();    }

6.接受写入管道输出流的所提供的数据字节的PipedInputStream
需求说明:利用PipedInputStream读取管道输出流中的数据。

    //创建一个管道输入流    PipedInputStream pis = new PipedInputStream();    byte a[] = new byte[]{1,2,3,4,5,6};    byte b[] = new byte[1024];    //创建一个管道输出流    PipedOutputStream pos = new PipedOutputStream();    //将字节数组写入管道输出流    try{    //将输出流管道与输入流管道连接,不连接将抛出IO        pos.connect(pis);        pos.write(a,0,5);        //刷新管道输入流        pos.flush();        //读取管道输出流中的数据        pis.read(b);        System.out.println(b[0]);    } catch (IOException e) {        e.printStackTrace();    }finally{   //关闭管道输入流和管道输出流        try {   pos.close();                pis.close();        } catch (Exception e) {            System.out.println("发生IO异常!");}}

7.将数据写入管道的PipedOutputStream
需求说明:将字节数组写入管道输出流PipedOutputStream中。代码展示如上例。

8.将其他输入流逻辑串联,依次读取的SequenceInputStream
需求说明:将两个输入流连接在一起,依次读取两个输入流的数据。

    byte[] b = new byte[1024];    try(InputStream is1 = new FileInputStream("F:/1.txt");    InputStream is2 = new FileInputStream("F:/2.txt");    //创建SequenceInputStream对象,将两个输入连接             SequenceInputStream sis = new SequenceInputStream(is1,is2);)    {        //依次读取两个输入流        sis.read(b);    } catch (IOException e) {        e.printStackTrace();}    System.out.println(b[0]);

9.从文件中读取类的ObjectInputStream
需求说明:将ObjectOutputStream向文件中写入的类利ObjectInputStream读取出来。

    FileInputStream fis = new FileInputStream("F:/1.tmp");        //创建读取类的ObjectInputStream对象        ObjectInputStream ois = new ObjectInputStream(fis);        FileOutputStream fos = new FileOutputStream("F:/1.tmp");        //创建写入类的ObjectOutputStream对象        ObjectOutputStream oos = new ObjectOutputStream(fos);        //利用writeObject()方法向指定文件写入类        oos.writeObject("Today");        oos.close();    //利用readObject()方法读取指定文件的类返回的是object类,所以要进行强转        String time =(String)ois.readObject();        ois.close();        System.out.println(time);

10.向指定文件写入类的ObjectOutputStream
需求说明:利用ObjectOutputStream向文件中写入类。展示代码入上例。

11.StringBufferInputStream类现已过时在此不做使用说明。

12.FilterInputStream类展开,对其及其子类进行详细说明。

FilterInputStream包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。FilterInputStream的子LineNumberInputStream已过时不做说明
对FilterInputStream 的子类进行说明。

(1)缓冲输入以及支持 mark 和 reset 方法的BufferedInputStream
需求说明:利用BufferedInputStream接受键盘输入的数据。

byte b[] = new byte[1024];    try(    BufferedInputStream bis = new BufferedInputStream(System.in);        DataInputStream  dis = new DataInputStream(bis);)        {   //在输入流处做好标记,并保留1024位            dis.mark(1024);            //将键盘输入的数据读入字节数组b中            dis.read(b);            String a1 = new String(b,0,b.length);            System.out.println(a1);            //重新回到之前的标记处,再次读取数据            dis.reset();            dis.read(b);            String a2 = new String(b,0,b.length);            System.out.println(a2);        } catch (IOException e) {            e.printStackTrace();}

(2)校验和可用于验证输入数据的完整性的CheckedInputStream
需求说明:验证数据的完整性后,将数据读入数组。

byte b[] = new byte[1024];        //指定的校验和 ,Adler32是可用于计算数据流的 Adler-32 校验和的类        Checksum c = new Adler32();        try(InputStream is = new FileInputStream("F:/1.txt");            CheckedInputStream cis = new CheckedInputStream(is, c))        {            //返回当前的校验和值            c.getValue();            //将数据读入字节数组            cis.read(b);            cis.close();            System.out.println(b[0]);        } catch (Exception e) {            e.printStackTrace();}   

(3)读取加密数据的CipherInputStream
需求说明:利用CipherInputStream将加密数据读入。

    InputStream is = null;    //service为具体的值    try {   is = new FileInputStream("service");        //实例化KeyGenerator对象,指定一个算法 ,DES是一种转换名称,其他CBC、PKCS5Padding        KeyGenerator kg = KeyGenerator.getInstance("DES");        //生成SecretKey对象        SecretKey secrekey = kg.generateKey();        //实例化Cipher对象        Cipher c = Cipher.getInstance("DES");        //初始化Cipher对象,用于解密操作。        c.init(Cipher.DECRYPT_MODE,secrekey);        CipherInputStream cis = new CipherInputStream(is, c);         //使用DataInputStream对象包装CipherInputStream对象        DataInputStream dis = new DataInputStream(cis);        //将数据读入到字节数组        String utf = dis.readUTF();             System.out.println(utf);        } catch (Exception e) {            e.printStackTrace();        }finally {            try {i  s.close();            } catch (IOException e) {                e.printStackTrace();}}

(4)使用通过流的位更新关联消息摘要的透明流DigestInputStream
需求说明:利用DigestInputStream将数据读入,并带有消息摘要。

//使用指定的输入流和消息摘要创建一个摘要输入流。    InputStream is;    MessageDigest md;    DigestInputStream dis = null;    byte b [] = new byte[1024];    try {   is = new FileInputStream("F:/1.txt");        //此 MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法        md = MessageDigest.getInstance("MD5");        dis = new DigestInputStream(is, md);        //读取字节并更新消息摘要(如果开启了摘要功能)        dis.read(b);        System.out.println(b[0]);    } catch (Exception e) {        e.printStackTrace();    }finally{   try {            dis.close();            } catch (IOException e) {                e.printStackTrace();}}

(5)监视读取某些 InputStream 进度的ProgressMonitorInputStream
需求说明:利用DigestInputStream将数据读入,并进行监视。

InputStream is;    ProgressMonitorInputStream pmis = null;    byte b[] = new byte[1024];    try{        is = new FileInputStream("F:/1.txt");        String a = "Reading"+"F:/1.txt";         //构造一个对象,以监视输入流的进度。    pmis = new ProgressMonitorInputStream(new Button(), a, is);        //重写 FilterInputStream.read,以读取之后更新进度监视器。        pmis.read();        System.out.println(b[0]);    } catch (Exception e) {        e.printStackTrace();    }finally{   try {            pmis.close();            } catch (IOException e) {                e.printStackTrace();}}

(6)拥有推回和取消读取字节能力的PushbackInputStream
需求说明:利用PushbackInputStream将数据读入,并将数据推回,再次读取。

byte b[] = new byte[1024];    int num = 1;    try(InputStream is = new FileInputStream("F:/1.txt");    PushbackInputStream pis = new PushbackInputStream(is);)    {        pis.read(b);        System.out.println(b[0]);        //推回一个 byte数组:将其复制到推回缓冲区之前        pis.unread(num);        pis.read(b);        System.out.println(b[0]);    } catch (Exception e) {        e.printStackTrace();}

(7)允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型的DataInputStream
需求说明:利用DataInputStream将数据读入。

        byte[] b = new byte[1024];        try(InputStream is = new FileInputStream("F:/2.txt");        DataInputStream dis = new DataInputStream(is);)        {        //从输入流中读取字节,并将它们存储在缓冲区数组 b中            dis.read(b);            System.out.println(b[0]);        } catch (Exception e) {            e.printStackTrace();        }

(8)FilterInputStream下的特殊子类InflaterInputStream

InflaterInputStream为解压缩 “deflate” 压缩格式的数据实现流过滤器,其两个子类分别为:读取 ZIP 文件格式的文件实现输入流过滤器ZipInputStream和
读取 GZIP 文件格式的压缩数据实现流过滤器GZIPInputStream。

a.为读取 ZIP 文件格式的文件实现输入流过滤器的ZipInputStream

ZipInputStream可以得到压缩实体,但得不到压缩实体的流,流存贮在ZipEntry对象中。所以要想获得文件相对应的数据必须,将对应文件的ZipEntry对象创建出来。
每个压缩文件中都会存在多个子文件,每个子文件在java中ZipEntry来表示。
ZipInputStream对应的输出流类ZipOutputStream。
GZIPInputStream用于对GZIP格式的文件进行操作,GZIP 格式的文件用于UNIX系统的文件压缩,本ppt就不做详解,其对应输入流为DZIPOutputStream。对于文件的处理机制类似于ZipInputStream。
现在我们来看看利用ZipInputStream如何处理文件。

try(InputStream is = new FileInputStream("F:/2.txt");    ZipInputStream zis = new ZipInputStream(is);    FileOutputStream fos = new FileOutputStream(new File("F:/2.zip"));    ZipOutputStream zos = new ZipOutputStream(fos); )    {   //设置ZipEntry对象         ZipEntry ze = new ZipEntry("F:/2.txt");        // 设置ZipEntry对象         zos.putNextEntry(ze);        int temp = 0 ;          //将要压缩的文件利用ZipInputStream对象读入输出流中        while((temp=zis.read())!=-1){ // 读取内容              zos.write(temp) ;    // 压缩输出  }             System.out.println(ze.getName());        } catch (Exception e) {            e.printStackTrace();        }

b.对jar文件进行处理的特殊类:JarInputStream

jar压缩的支持类包括:
1)jar压缩输出流:JarOutputStream
2)jar压缩输入流:JarOutputStream
3)jar文件:JARFILE
4)jar实体:JAREntry
接下来对jar压缩进行举例说明。

        //创建输入输出流try(    JarInputStream jis = new JarInputStream(new FileInputStream("F:/2.txt"));    JarOutputStream jos = new JarOutputStream(new FileOutputStream("F:/2.jar")))        {            //创建对应的JarEntry对象            JarEntry ze = new JarEntry("F:/2.txt");            //向输出流中设置ZipEntry对象            jos.putNextEntry(ze);            //将文件压缩输出            int temp = 0;            while((temp=jis.read())!=-1){                jos.write(temp);            }        } catch (Exception e) {            e.printStackTrace();        }注:该实例直接使用FileInputStream类,未使用JarFile类

(9)对文件进行随机读取的RandomAccessFile

//public RandomAccessFile(File file, String mode)//该构造方法创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。//mode 参数指定用以打开文件的访问模式    File f = new File("F:/1.txt");    try(RandomAccessFile raf = new RandomAccessFile(f,"rw");)    {        //随机读取文件中的一个字节        int num = raf.read();        System.out.println(num);    } catch (Exception e) {        e.printStackTrace();    }

五.作者总结

通过写作该本的制作收获以下心得体会:
1、在进行流操作时,最后一定要将流关闭。该ppt中的实例,作者根据不同的情况,采用了不同的关流方法,包括java7中的Try-With-ResourcesStatement格式。
2、每个特定流的类,可能都有它的特定格式,理解了这种格式,有利于对流的运用。
3、基本上每个特定的InputStream类都有对应的OutputStream类,其实不同类在文件的读取和写入上都存在共同点。

备注:
FilterOutputStream中的子类并未挨个展开,其原理和使用与其他的OutputStream一致。

0 0
原创粉丝点击