`
newleague
  • 浏览: 1504354 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

Java流操作,InputStream、OutputStream及子类FileInputStream、FileOutputStream;BufferedInpu

阅读更多

Java将数据于目的地及来源之间的流动抽象化为一个流(Stream),而流当中流动的则是位数据。

14.2.1 InputStream和OutputStream

计算机中实际上数据的流动是通过电路,而上面流动的则是电流,电流的电位有低位与高位,即数字的0与1位。从程序的观点来说,通常会将数据目的地(例如内存)与来源(例如文件)之间的数据流动抽象化为一个流(Stream),而其中流动的则是位数据,如图14-1所示。

 

图14-1  数据的流动抽象化为流的概念

在Java SE中有两个类用来作流的抽象表示:java.io.InputStream与java.io.OutputStream。

InputStream 是所有表示位输入流的类之父类,它是一个抽象类,继承它的子类要重新定义其中所定义的抽象方法。InputStream是从装置来源地读取数据的抽象表示,例如System中的标准输入流in对象就是一个InputStream类型的实例。在Java程序开始之后,in流对象就会开启,目的是从标准输入装置中读取数据,这个装置通常是键盘或是用户定义的输入装置。

OutputStream 是所有表示位输出流的类之父类,它是一个抽象类。子类要重新定义其中所定义的抽象方法,OutputStream是用于将数据写入目的地的抽象表示。例如 System中的标准输出流对象out其类型是java.io.PrintStream,这个类是OutputStream的子类 (java.io.FilterOutputStream继承OutputStream, PrintStream再继承FilterOutputStream)。在程序开始之后,out流对象就会开启,可以通过out来将数据写至目的地装置,这个装置通常是屏幕显示或用户定义的输出装置。

范例14.4可以读取键盘输入流,in对象的read()方法一次读取一个字节的数据,读入的数据以int类型返回。所以在使用out对象将数据显示出来时,就是10进制方式。

ü 范例14.4  StreamDemo.java

package onlyfun.caterpillar;

import java.io.*;

public class StreamDemo {

    public static void main(String[] args) {

        try {

            System.out.print("输入字符: ");

            System.out.println("输入字符十进制表示: " +

                                    System.in.read());

        }

        catch(IOException e) {

            e.printStackTrace();

        }

    }

}

执行结果:

输入字符: A

输入字符十进制表示: 65

字符A输入后由标准输入流in读取,A的位表示以十进制来看就是65,这是A字符的编码(查查ASCII编码表就知道了)。

一般来说,很少直接实现InputStream或OutputStream上的方法,因为这些方法比较低级,通常会实现它们的子类。这些子类上所定义的方法在进行输入/输出时更为方便。

14.2.2 FileInputStream和FileOutputStream

java.io.FileInputStream 是InputStream的子类。从开头File名称上就可以知道,FileInputStream与从指定的文件中读取数据至目的地有关。而 java.io.FileOutputStream是OutputStream的子类,顾名思义,FileOutputStream主要与从来源地写入数据至指定的文件中有关。

当建立一个FileInputStream或FileOutputStream的实例时,必须指定文件位置及文件名称,实例被建立时文件的流就会开启;而不使用流时,必须关闭文件流,以释放与流相依的系统资源,完成文件读/写的动作。

FileInputStream可以使用 read()方法一次读入一个字节,并以int类型返回,或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少个字节。在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区,因为这么一个byte数组通常扮演承接数据的中间角色。

范例14.5是使用FileInputStream与FileOutputStream的一个例子。程序可以复制文件,它会先从来源文件读取数据至一个byte数组中,然后再将byte数组的数据写入目的文件。

ü 范例14.5  FileStreamDemo.java

package onlyfun.caterpillar;

import java.io.*;

public class FileStreamDemo {

    public static void main(String[] args) {

        try {

            byte[] buffer = new byte[1024];

            // 来源文件

            FileInputStream fileInputStream =

                new FileInputStream(new File(args[0]));

            // 目的文件

            FileOutputStream fileOutputStream =

                new FileOutputStream(new File(args[1]));

            // available()可取得未读取的数据长度

            System.out.println("复制文件:" +

                    fileInputStream.available() + "字节");

          

            while(true) {

                if(fileInputStream.available() < 1024) {

                    // 剩余的数据比1024字节少

                    // 一位一位读出再写入目的文件

                    int remain = -1;

                    while((remain = fileInputStream.read())

                                           != -1) {

                        fileOutputStream.write(remain);

                    }

                    break;

                }

                else {

                    // 从来源文件读取数据至缓冲区

                    fileInputStream.read(buffer);

                    // 将数组数据写入目的文件

                    fileOutputStream.write(buffer);

                }

            }

            // 关闭流

            fileInputStream.close();

            fileOutputStream.close();

            System.out.println("复制完成");

        }

        catch(ArrayIndexOutOfBoundsException e) {

            System.out.println(

                      "using: java FileStreamDemo src des");

            e.printStackTrace();

        }

        catch(IOException e) {

            e.printStackTrace();

        }

    }

}

程序中示范了两个read()方法,一个方法可以读入指定长度的数据至数组,另一个方法一次可以读入一个字节。每次读取之后,读取的光标都会往前进,如果读不到数据则返回–1,使用available()方法获得还有多少字节可以读取。除了使用File来建立FileInputStream、 FileOutputStream的实例之外,也可以直接使用字符串指定路径来建立。

// 来源文件FileInputStream fileInputStream =                new FileInputStream(args[0]);// 目的文件FileOutputStream fileOutputStream =                new FileOutputStream(args[1]);在不使用文件流时,记得使用close()方法自行关闭流,以释放与流相依的系统资源。一个执行的结果范例如下,它将FileDemo.java复制为FileDemo.txt:

java onlyfun.caterpillar.FileStreamDemo FileDemo.java FileDemo.txt

复制文件:1723字节

复制完成

FileOutputStream默认会以新建文件的方式来开启流。如果指定的文件名称已经存在,则原文件会被覆盖;如果想以附加的模式来写入文件,则可以在构建FileOutputStream实例时指定为附加模式。例如:

FileOutputStream fileOutputStream =                new FileOutputStream(args[1], true);构建方法的第二个append参数如果设置为true,在开启流时如果文件不存在则会新建一个文件,如果文件存在就直接开启流,并将写入的数据附加至文件末端。

 

虽然我一向不喜欢使用过长的范例来作程序示范(也不喜欢看很长的范例),不过本章的范例与其他各章的比起来相对长了一些,我会在程序中多用注释解释程序的逻辑。因为解释输入/输出操作最好的方式,是呈现一个具实用性的范例,本章的范例除了练习的作用之外,日后需要某些输入/输出功能时,也可以来参考看看如何实现。

14.2.3 BufferedInputStream和BufferedOutputStream

在介绍FileInputStream和 FileOutputStream的例子中,使用了一个byte数组来作为数据读入的缓冲区,以文件存取为例,硬盘存取的速度远低于内存中的数据存取速度。为了减少对硬盘的存取,通常从文件中一次读入一定长度的数据,而写入时也是一次写入一定长度的数据,这可以增加文件存取的效率。

java.io.BufferedInputStream 与java.io.BufferedOutputStream可以为InputStream、OutputStream类的对象增加缓冲区功能。构建 BufferedInputStream实例时,需要给定一个InputStream类型的实例,实现BufferedInputStream时,实际上最后是实现InputStream实例。同样地,在构建BufferedOutputStream时,也需要给定一个OutputStream实例,实现 BufferedOutputStream时,实际上最后是实现OutputStream实例。

BufferedInputStream的数据成员buf是一个位数组,默认为2048字节。当读取数据来源时,例如文件,BufferedInputStream会尽量将buf填满。当使用read ()方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取。当buf中的数据不足时,BufferedInputStream才会再实现给定的InputStream对象的read()方法,从指定的装置中提取数据,如图14-2所示。

 

图14-2  BufferedInputStream在内部有buf成员作为缓冲区

BufferedOutputStream的数据成员buf是一个位数组,默认为512字节。当使用write()方法写入数据时,实际上会先将数据写至buf中,当buf已满时才会实现给定的 OutputStream对象的write()方法,将buf数据写至目的地,而不是每次都对目的地作写入的动作。

下面将范例14.5做个改写,这次不用自行设置缓冲区,而使用BufferedInputStream和BufferedOutputStream让程序看来简单一些,也比较有效率。

ü 范例14.6  BufferedStreamDemo.java

package onlyfun.caterpillar;

import java.io.*;

public class BufferedStreamDemo {

    public static void main(String[] args) {

        try {

            byte[] data = new byte[1];

            File srcFile = new File(args[0]);

            File desFile = new File(args[1]);

            BufferedInputStream bufferedInputStream =

                new BufferedInputStream(

                         new FileInputStream(srcFile));

            BufferedOutputStream bufferedOutputStream =

                new BufferedOutputStream(

                         new FileOutputStream(desFile));

            System.out.println("复制文件:" +

                             srcFile.length() + "字节");

            while(bufferedInputStream.read(data) != -1) {

                bufferedOutputStream.write(data);

            }

          

            // 将缓冲区中的数据全部写出

            bufferedOutputStream.flush();

            // 关闭流

            bufferedInputStream.close();

            bufferedOutputStream.close();

            System.out.println("复制完成");

        }

        catch(ArrayIndexOutOfBoundsException e) {

            System.out.println(

                    "using: java UseFileStream src des");

            e.printStackTrace();

        }

        catch(IOException e) {

            e.printStackTrace();

        }

    }

}

为了确保缓冲区中的数据一定被写出至目的地,建议最后执行flush()将缓冲区中的数据全部写出目的流中。这个范例的执行结果与范例14.5是相同的。

BufferedInputStream和 BufferedOutputStream并没有改变InputStream或 OutputStream的行为,读入或写出时的动作还是InputStream和OutputStream负责。 BufferedInputStream和BufferedOutputStream只是在操作对应的方法之前,动态地为它们加上一些额外功能(像缓冲区功能),在这里是以文件存取流为例,实际上可以在其他流对象上也使用BufferedInputStream和BufferedOutputStream 功能。

分享到:
评论

相关推荐

    将输出流OutputStream转化为输入流InputStream的方法

    在Java中,它们是Java.io包下的基础类,提供了多种子类来处理不同类型的输出和输入操作,如`FileOutputStream`和`FileInputStream`用于文件操作,`SocketOutputStream`和`SocketInputStream`用于网络通信等。...

    InputStream与OutputStream及File间互转

    在Java编程语言中,`InputStream`和`OutputStream`是处理数据流的核心类,它们属于Java的I/O(Input/Output)框架。`File`类则用于处理文件操作,如读写、创建、删除等。理解如何在这些对象之间进行转换是Java开发中...

    java 文件存储 Inputstream outputstream reader writer的用法

    `InputStream`、`OutputStream`、`Reader`和`Writer`是Java IO流的基础类,它们提供了读写文件的基本接口。本篇文章将深入讲解这些类的用法,并提供实际的代码示例,帮助初学者更好地理解和应用。 1. `InputStream`...

    IO流文档InputStream / OutputStream

    IO流是一种基本的数据交换方式,在Java中,IO流是通过输入流(InputStream)和输出流(OutputStream)来实现的。输入流用于读取数据,而输出流用于写入数据。 InputStream是所有输入流的抽象超类,它提供了基本的...

    Java基础核心+InputStream输入流+OutputStream输出流

    本教程将聚焦于Java的基础核心,以及两个重要的I/O(输入/输出)流类——InputStream和OutputStream,它们在文件操作中扮演着关键角色。 InputStream和OutputStream是Java.io包下的抽象类,是所有字节流的基类。...

    java io InputStream and outputStream

    InputStream is = new FileInputStream(file1);// 打开文件 byte[] cont = new byte[(int) file1.length()]; is.read(cont);// 读取文件 for (int i = 0; i ; i++) { System.out.print((char) ...

    java io 类 小结 代码

    InputStream OutputStream Reader Writer FileInputStream FileOutputStream FileReader FileWriter InputStreamReader OutputStreamWriter BufferedReader BufferedWriter PrintWriter ...

    Java中文件IO流.pdf

    InputStream 是 Java 中的输入流接口,用于读取文件的内容,常用的 InputStream 子类包括 FileInputStream、BufferedInputStream、DataInputStream 等。FileInputStream 是 InputStream 的子类,用于打开一个输入...

    JavaIo流分析图

    分析Java常用IO流,包括InputStream、OutputStream、FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream、Reader、Writer、InputStreamReader、OutputStreamWriter、FileReader、...

    【IT十八掌徐培成】Java基础第13天-04.字节流-FileInputStream-FileOutputStream.zip

    本课程由IT十八掌徐培成讲解,重点介绍了Java基础中的字节流操作,特别是`FileInputStream`和`FileOutputStream`这两个核心类的使用。 `FileInputStream`和`FileOutputStream`是Java.io包下的核心类,它们分别代表...

    IO流 javaio java 流

    它们又可以进一步细分为输入流(InputStream/Reader)和输出流(OutputStream/Writer),分别用于数据的读取和写入。 1. 字节流: - 字节输入流(InputStream):如FileInputStream,用于从文件系统读取字节数据。...

    Java流(文件读写操作)

    ### Java流(文件读写操作) #### 一、流的分类 Java中处理文件和数据时,使用流的概念来进行操作。根据不同的标准,流可以分为几种类型。 ##### 1. 按数据流动方向 - **输入流**:主要用于从数据源读取数据。输入...

    Java流操作文件

    - **字节流**:主要包括`InputStream`和`OutputStream`抽象类,它们分别用于读取和写入字节数据。常用的子类有`FileInputStream`和`FileOutputStream`,它们专门用于文件的读写操作。 - `FileInputStream`:用于从...

    java中的IO流操作大全

    在Java中,所有的流都实现了java.io包中的InputStream、OutputStream、Reader、Writer这些抽象类,它们分别是字节流和字符流的基类。 二、流的分类 Java的IO流主要分为两大类:字节流和字符流。 1. 字节流 字节...

    java文件与流操作code

    - 字节流:Java中的InputStream和OutputStream是所有字节输入流和输出流的基类,包括FileInputStream、FileOutputStream等,用于处理二进制数据,如图片、音频等。 - 字符流:Reader和Writer是所有字符输入流和...

    【Sansui】java各种流整理demo

    java各类IO流的整理demo,其内包含InputStream/OutputStream BufferedReader流 FileOutputStream/FileInputStream流 PrintWriter流 DataOut/DataIn流 Object流 FileChannel类;

    java流详细介绍

    理解并掌握InputStream、OutputStream、Reader和Writer的基本原理及用法对于开发高质量的Java应用程序至关重要。此外,通过使用高级流,如缓冲流和数据流,还可以进一步提高程序的效率和功能性。希望本文能够帮助您...

    FileInputStream 和 FileOutputStream 介绍_动力节点Java学院整理

    FileInputStream 是文件输入流,它继承于InputStream。 通常,我们使用FileInputStream从某个文件中获得输入字节。 FileOutputStream 是文件输出流,它继承于OutputStream。 通常,我们使用FileOutputStream 将数据...

    java流.rarjava流.rar

    - 字节输入流(InputStream):如FileInputStream,用于从各种源(如文件、网络等)读取字节数据。 - 字节输出流(OutputStream):如FileOutputStream,用于向目的地(如文件、网络等)写入字节数据。 - 链接流...

Global site tag (gtag.js) - Google Analytics