zoukankan      html  css  js  c++  java
  • java_io

    JAVA IO流(一)
    参考文章:http://ifeve.com/java-io-network/,并发编程网
    原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java IO教程
    Java的IO包主要关注的是从原始数据源的读取以及输出原始数据到目标媒介。以下是最典型的数据源和目标媒介:
    文件
    管道
    网络连接
    内存缓存
    System.in, System.out, System.error(注:Java标准输入、输出、错误输出)

    类InputStream, OutputStream, Reader 和Writer
    一个程序需要InputStream或者Reader从数据源读取数据,需要OutputStream或者Writer将数据写入到目标媒介中。
    InputStream和Reader与数据源相关联,OutputStream和writer与目标媒介相关联。
    Java IO的用途和特征
    Java IO中包含了许多InputStream、OutputStream、Reader、Writer的子类。这样设计的原因是让每一个类都负责不同的功能。这也就是为什么IO包中有这么多不同的类的缘故。各类用途汇总如下:

    文件访问
    网络访问
    内存缓存访问
    线程内部通信(管道)
    缓冲
    过滤
    解析
    读写文本 (Readers / Writers)
    读写基本类型数据 (long, int etc.)
    读写对象
    当通读过Java IO类的源代码之后,我们很容易就能了解这些用途。这些用途或多或少让我们更加容易地理解,不同的类用于针对不同业务场景。

    1、读写文件
    通过Java IO读文件
    如果你需要在不同端之间读取文件,你可以根据该文件是二进制文件还是文本文件来选择使用FileInputStream或者FileReader。这两个类允许你从文件开始到文件末尾一次读取一个字节或者字符,或者将读取到的字节写入到字节数组或者字符数组。你不必一次性读取整个文件,相反你可以按顺序地读取文件中的字节和字符。
    通过Java IO写文件
    如果你需要在不同端之间进行文件的写入,你可以根据你要写入的数据是二进制型数据还是字符型数据选用FileOutputStream或者FileWriter。你可以一次写入一个字节或者字符到文件中,也可以直接写入一个字节数组或者字符数据。数据按照写入的顺序存储在文件当中。
    文件和目录信息的获取
    有时候你可能需要读取文件的信息而不是文件的内容,举个例子,如果你需要知道文件的大小和文件的属性。对于目录来说也是一样的,比如你需要获取某个目录下的文件列表。通过File类可以获取文件和目录的信息。

    2、Java IO: 网络
    当两个进程之间建立了网络连接之后,他们通信的方式如同操作文件一样:利用InputStream读取数据,利用OutputStream写入数据。换句话来说,Java网络API用来在不同进程之间建立网络连接,而Java IO则用来在建立了连接之后的进程之间交换数据。

    基本上意味着如果你有一份能够对文件进行写入某些数据的代码,那么这些数据也可以很容易地写入到网络连接中去。你所需要做的仅仅只是在代码中利用InputStream替代FileInputStream进行数据的写入。因为FileInputStream是InputStream的子类,所以这么做并没有什么问题。(译者注:此处应该是OutputStream和FileOutputStream)

    实际上对于文件的读操作也类似,一个具有读取文件数据功能的组件,同样可以轻松读取网络连接中的数据。只需要保证读取数据的组件是基于InputStream而非FileInputStream即可。
    public class MyClass {

    public static void main(String[] args) {
    InputStream inputStream = new FileInputStream("c:\myfile.txt");
    process(inputStream);
    }

    public static void process(InputStream input) throws IOException {
    //do something with the InputStream
    }

    }
    在这个例子中,process()方法并不关心InputStream参数的输入流,是来自于文件还是网络(例子只展示了输入流来自文件的版本)。process()方法只会对InputStream进行操作。
    3、Java IO: 字节和字符数组
    原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java IO: 字节和字符数组
    内容列表

    从InputStream或者Reader中读入数组
    从OutputStream或者Writer中写数组
    在java中常用字节和字符数组在应用中临时存储数据。而这些数组又是通常的数据读取来源或者写入目的地。如果你需要在程序运行时需要大量读取文件里的内容,那么你也可以把一个文件加载到数组中。当然你可以通过直接指定索引来读取这些数组。但如果设计成为从InputStream或者Reader,而不是从数组中读取某些数据的话,你会用什么组件呢?


    从 InputStream 或 Reader中读取数组

    用ByteArrayInputStream或者CharArrayReader封装字节或者字符数组从数组中读取数据。通过这种方式字节和字符就可以以数组的形式读出了。

    样例如下
    byte[] bytes = new byte[1024];

     

    //把数据写入字节数组...

     

    InputStream input = new ByteArrayInputStream(bytes);

     

    //读取第一个字节

    int data = input.read();

    while(data != -1) {

    //操作数据

     

    //读下一个字节

    data = input.read();

    }
    以同样的方式也可以用于读取字符数组,只要把字符数组封装在CharArrayReader上就行了。

    通过 OutputStream 或者 Writer写数组

    同样,也可以把数据写到ByteArrayOutputStream或者CharArrayWriter中。你只需要创建ByteArrayOutputStream或者CharArrayWriter,把数据写入,就像写其它的流一样。当所有的数据都写进去了以后,只要调用toByteArray()或者toCharArray,所有写入的数据就会以数组的形式返回。

    样例如下:
    OutputStream output = new ByteArrayOutputStream();

     

    output.write("This text is converted to bytes".toBytes("UTF-8"));

     

    byte[] bytes = output.toByteArray();
    写字符数组也和此例子类似。只要把字符数组封装在CharArrayWriter上就可以了。
    4、流
    Java IO流是既可以从中读取,也可以写入到其中的数据流,流通常会与数据源、数据流向目的地相关联,比如文件、网络等等。流仅仅只是一个连续的数据流。
    Java IO流通常是基于字节或者基于字符的。字节流通常以“stream”命名,比如InputStream和OutputStream。字符流通常以“Reader”或者“Writer”命名。字符流能够读写字符(比如Latin1或者Unicode字符)。
    InputStream
    java.io.InputStream类是所有Java IO输入流的基类。如果你正在开发一个从流中读取数据的组件,请尝试用InputStream替代任何它的子类(比如FileInputStream)进行开发。这么做能够让你的代码兼容任何类型而非某种确定类型的输入流。

    然而仅仅依靠InputStream并不总是可行。如果你需要将读过的数据推回到流中,你必须使用PushbackInputStream,这意味着你的流变量只能是这个类型,否则在代码中就不能调用PushbackInputStream的unread()方法。

    通常使用输入流中的read()方法读取数据。read()方法返回一个整数,代表了读取到的字节的内容(译者注:0 ~ 255)。当达到流末尾没有更多数据可以读取的时候,read()方法返回-1。

    这是一个简单的示例:
    InputStream input = new FileInputStream("c:\data\input-file.txt");

    int data = input.read();

    while(data != -1){

    data = input.read();

    }
    OutputStream
    java.io.OutputStream是Java IO中所有输出流的基类。如果你正在开发一个能够将数据写入流中的组件,请尝试使用OutputStream替代它的所有子类。

    这是一个简单的示例:
    OutputStream output = new FileOutputStream("c:\data\output-file.txt");
    output.write("Hello World".getBytes());
    output.close();
    组合流
    你可以将流整合起来以便实现更高级的输入和输出操作。比如,一次读取一个字节是很慢的,所以可以从磁盘中一次读取一大块数据,然后从读到的数据块中获取字节。为了实现缓冲,可以把InputStream包装到BufferedInputStream中。代码示例:
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"));
    缓冲同样可以应用到OutputStream中。你可以实现将大块数据批量地写入到磁盘(或者相应的流)中,这个功能由BufferedOutputStream实现。

    缓冲只是通过流整合实现的其中一个效果。

    5、Reader
    Reader类是Java IO中所有Reader的基类。子类包括BufferedReader,PushbackReader,InputStreamReader,StringReader和其他Reader。
    这是一个简单的Java IO Reader的例子:
    Reader reader = new FileReader("c:\data\myfile.txt");
    int data = reader.read();
    while(data != -1){
    char dataChar = (char) data;
    data = reader.read();
    }
    请注意,InputStream的read()方法返回一个字节,意味着这个返回值的范围在0到255之间(当达到流末尾时,返回-1),Reader的read()方法返回一个字符,意味着这个返回值的范围在0到65535之间(当达到流末尾时,同样返回-1)。这并不意味着Reade只会从数据源中一次读取2个字节,Reader会根据文本的编码,一次读取一个或者多个字节。
    你通常会使用Reader的子类,而不会直接使用Reader。Reader的子类包括InputStreamReader,CharArrayReader,FileReader等等
    整合Reader与InputStream
    一个Reader可以和一个InputStream相结合。如果你有一个InputStream输入流,并且想从其中读取字符,可以把这个InputStream包装到InputStreamReader中。把InputStream传递到InputStreamReader的构造函数中:

    Reader reader = new InputStreamReader(inputStream);
    在构造函数中可以指定解码方式
    Writer
    Writer类是Java IO中所有Writer的基类。子类包括BufferedWriter和PrintWriter等等。这是一个Java IO Writer的例子:
    Writer writer = new FileWriter("c:\data\file-output.txt");
    writer.write("Hello World Writer");
    writer.close();
    同样,你最好使用Writer的子类,不需要直接使用Writer,因为子类的实现更加明确,更能表现你的意图。常用子类包括OutputStreamWriter,CharArrayWriter,FileWriter等。Writer的write(int c)方法,会将传入参数的低16位写入到Writer中,忽略高16位的数据。
    整合Writer和OutputStream
    与Reader和InputStream类似,一个Writer可以和一个OutputStream相结合。把OutputStream包装到OutputStreamWriter中,所有写入到OutputStreamWriter的字符都将会传递给OutputStream。这是一个OutputStreamWriter的例子:

    Writer writer = new OutputStreamWriter(outputStream);

    整合Reader和Writer
    和字节流一样,Reader和Writer可以相互结合实现更多更有趣的IO,工作原理和把Reader与InputStream或者Writer与OutputStream相结合类似。举个栗子,可以通过将Reader包装到BufferedReader、Writer包装到BufferedWriter中实现缓冲。以下是例子:
    Reader reader = new BufferedReader(new FileReader(...));
    Writer writer = new BufferedWriter(new FileWriter(...));
    6、IO 并发
    有时候你可能需要并发地处理输入和输出。换句话说,你可能有超过一个线程处理输入和产生输出。比如,你有一个程序需要处理磁盘上的大量文件,这个任务可以通过并发操作提高性能。又比如,你有一个web服务器或者聊天服务器,接收许多连接和请求,这些任务都可以通过并发获得性能的提升。
    如果你需要并发处理IO,这里有几个问题可能需要注意一下:
    在同一时刻不能有多个线程同时从InputStream或者Reader中读取数据,也不能同时往OutputStream或者Writer里写数据。你没有办法保证每个线程读取多少数据,以及多个线程写数据时的顺序。
    如果线程之间能够保证操作的顺序,它们可以使用同一个stream、reader、writer。比如,你有一个线程判断当前的输入流来自哪种类型的请求,然后将流数据传递给其他合适的线程做后续处理。当有序存取流、reader、writer时,这种做法是可行的。请注意,在线程之间传递流数据的代码应当是同步的。
    注意:在Java NIO中,你可以让一个线程读写多个“channel”。比如,你有很多网络连接处于开启状态,但是每个连接中都只有少量数据,类似于聊天服务器,可以让一个线程监视多个频道(连接)。
    7、Java IO: InputStream
    InputStream类是Java IO API中所有输入流的基类。InputStream子类包括FileInputStream,BufferedInputStream,PushbackInputStream等等。
    Java InputStream例子
    InputStream用于读取基于字节的数据,一次读取一个字节,这是一个InputStream的例子:
    InputStream inputstream = new FileInputStream("c:\data\input-text.txt");
    int data = inputstream.read();
    while(data != -1) {
    //do something with data...
    doSomethingWithData(data);
    data = inputstream.read();
    }
    inputstream.close();
    这个例子创建了FileInputStream实例。FileInputStream是InputStream的子类,所以可以把FileInputStream实例赋值给InputStream变量。
    read()
    read()方法返回从InputStream流内读取到的一个字节内容(译者注:0~255),例子如下:
    int data = inputstream.read();
    你可以把返回的int类型转化成char类型:
    char aChar = (char) data;
    InputStream的子类可能会包含read()方法的替代方法。比如,DataInputStream允许你利用readBoolean(),readDouble()等方法读取Java基本类型变量int,long,float,double和boolean。
    流末尾
    如果read()方法返回-1,意味着程序已经读到了流的末尾,此时流内已经没有多余的数据可供读取了。-1是一个int类型,不是byte或者char类型,这是不一样的。
    当达到流末尾时,你就可以关闭流了。
    read(byte[])
    InputStream包含了2个从InputStream中读取数据并将数据存储到缓冲数组中的read()方法,他们分别是:
    int read(byte[])
    int read(byte, int offset, int length)
    一次性读取一个字节数组的方式,比一次性读取一个字节的方式快的多,所以,尽可能使用这两个方法代替read()方法。
    read(byte[])方法会尝试读取与给定字节数组容量一样大的字节数,返回值说明了已经读取过的字节数。如果InputStream内可读的数据不足以填满字节数组,那么数组剩余的部分将包含本次读取之前的数据。记得检查有多少数据实际被写入到了字节数组中。
    read(byte, int offset, int length)方法同样将数据读取到字节数组中,不同的是,该方法从数组的offset位置开始,并且最多将length个字节写入到数组中。同样地,read(byte, int offset, int length)方法返回一个int变量,告诉你已经有多少字节已经被写入到字节数组中,所以请记得在读取数据前检查上一次调用read(byte, int offset, int length)的返回值。
    这两个方法都会在读取到达到流末尾时返回-1。
    这是一个使用InputStream的read(byte[])的例子:
    InputStream inputstream = new FileInputStream("c:\data\input-text.txt");
    byte[] data = new byte[1024];
    int bytesRead = inputstream.read(data);
    while(bytesRead != -1) {
    doSomethingWithData(data, bytesRead);
    bytesRead = inputstream.read(data);
    }
    inputstream.close();
    在代码中,首先创建了一个字节数组。然后声明一个叫做bytesRead的存储每次调用read(byte[])返回值的int变量,并且将第一次调用read(byte[])得到的返回值赋值给它。
    在while循环内部,把字节数组和已读取字节数作为参数传递给doSomethingWithData方法然后执行调用。在循环的末尾,再次将数据写入到字节数组中。
    你不需要想象出read(byte, int offset, int length)替代read(byte[])的场景,几乎可以在使用read(byte, int offset, int length)的任何地方使用read(byte[])。

    Java IO: OutputStream
    OutputStream类是Java IO API中所有输出流的基类。子类包括BufferedOutputStream,FileOutputStream等等。
    输出流和目标媒介
    输出流往往和某些数据的目标媒介相关联,比如文件,网络连接,管道等。
    Write(byte)
    write(byte)方法用于把单个字节写入到输出流中。OutputStream的write(byte)方法将一个包含了待写入数据的int变量作为参数进行写入。只有int类型的第一个字节会被写入,其余位会被忽略。
    OutputStream的子类可能会包含write()方法的替代方法。比如,DataOutputStream允许你利用writeBoolean(),writeDouble()等方法将基本类型int,long,float,double,boolean等变量写入。
    这是一个OutputStream的write()方法例子:
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    while(hasMoreData()) {
    int data = getMoreData();
    output.write(data);
    }
    output.close();
    这个例子首先创建了待写入的FileOutputStream。在进入while循环之后,循环的判断条件是hasMoreData()方法的返回值。hasMoreData()方法的实现不予展示,请把这个函数理解为:当有剩余可写数据时,返回true,否则返回false。
    write(byte[])
    OutputStream同样包含了将字节数据中全部或者部分数据写入到输出流中的方法,分别是write(byte[])和write(byte[], int offset, int length)。
    write(byte[])把字节数组中所有数据写入到输出流中。
    write(byte[], int offset, int length)把字节数据中从offset位置开始,length个字节的数据写入到输出流。
    flush()
    OutputStream的flush()方法将所有写入到OutputStream的数据冲刷到相应的目标媒介中。比如,如果输出流是FileOutputStream,那么写入到其中的数据可能并没有真正写入到磁盘中。即使所有数据都写入到了FileOutputStream,这些数据还是有可能保留在内存的缓冲区中。通过调用flush()方法,可以把缓冲区内的数据刷新到磁盘(或者网络,以及其他任何形式的目标媒介)中。
    close()
    当你结束数据写入时,需要关闭OutputStream。通过调用close()可以达到这一点。因为OutputStream的各种write()方法可能会抛出IO异常,所以你需要把调用close()的关闭操作方在finally块中执行。这是一个OutputStream调用close()的例子:
    OutputStream output = null;
    try{
    output = new FileOutputStream("c:\data\output-text.txt");
    while(hasMoreData()) {
    int data = getMoreData();
    output.write(data);
    }
    } finally {
    if(output != null) {
    output.close();
    }

    }


    Java IO: FileInputStream
    FileInputStream可以以字节流的形式读取文件内容。FileInputStream是InputStream的子类,这意味着你可以把FileInputStream当做InputStream使用(FileInputStream与InputStream的行为类似)。
    InputStream input = new FileInputStream("c:\data\input-text.txt");
    int data = input.read();while(data != -1) {
    //do something with data...
    doSomethingWithData(data);
    data = input.read();
    }
    input.close();
    FileInputStream的read()方法返回读取到的包含一个字节内容的int变量(译者注:0~255)。如果read()方法返回-1,意味着程序已经读到了流的末尾,此时流内已经没有多余的数据可供读取了,你可以关闭流。-1是一个int类型,不是byte类型,这是不一样的。
    FileInputStream也有其他的构造函数,允许你通过不同的方式读取文件

    其中一个FileInputStream构造函数取一个File对象替代String对象作为参数。
    File file = new File("c:\data\input-text.txt");
    InputStream input = new FileInputStream(file);
    至于你该采用参数是String对象还是File对象的构造函数,取决于你当前是否已经拥有一个File对象,也取决于你是否要在打开FileOutputStream之前通过File对象执行某些检查(比如检查文件是否存在)。


    Java IO: FileOutputStream
    FileOutputStream可以往文件里写入字节流,它是OutputStream的子类,所以你可以像使用OutputStream那样使用FileOutputStream。
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    while(moreData) {
    int data = getMoreData();
    output.write(data);
    }
    output.close();
    FileOutputStream的write()方法取一个包含了待写入字节(译者注:低8位数据)的int变量作为参数进行写入。
    FileOutputStream也有其他的构造函数,允许你通过不同的方式写入文件。
    文件内容的覆盖Override VS追加Appending
    当你创建了一个指向已存在文件的FileOutputStream,你可以选择覆盖整个文件,或者在文件末尾追加内容。通过使用不同的构造函数可以实现不同的目的。
    其中一个构造函数取文件名作为参数,会覆盖任何此文件名指向的文件。
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    另外一个构造函数取2个参数:文件名和一个布尔值,布尔值表明你是否需要覆盖文件。这是构造函数的例子:
    OutputStream output = new FileOutputStream("c:\data\output-text.txt", true); //appends to file
    OutputStream output = new FileOutputStream("c:\data\output-text.txt", false); //overwrites file
    写入字节数组
    既然FileOutputStream是OutputStream的子类,所以你也可以往FileOutputStream中写入字节数组,而不需要每次都只写入一个字节。可以参考我的OutputStream教程查阅更多关于写入字节数组的信息。
    flush()
    当你往FileOutputStream里写数据的时候,这些数据有可能会缓存在内存中。在之后的某个时间,比如,每次都只有X份数据可写,或者FileOutputStream关闭的时候,才会真正地写入磁盘。当FileOutputStream没被关闭,而你又想确保写入到FileOutputStream中的数据写入到磁盘中,可以调用flush()方法,该方法可以保证所有写入到FileOutputStream的数据全部写入到磁盘中。

    Java IO: File
    java IO API中的FIle类可以让你访问底层文件系统,通过File类,你可以做到以下几点:
    检测文件是否存在
    读取文件长度
    重命名或移动文件
    删除文件
    检测某个路径是文件还是目录
    读取目录中的文件列表
    请注意:File只能访问文件以及文件系统的元数据。如果你想读写文件内容,需要使用FileInputStream、FileOutputStream或者RandomAccessFile。如果你正在使用Java NIO,并且想使用完整的NIO解决方案,你会使用到java.nio.FileChannel(否则你也可以使用File)。
    实例化一个java.io.File对象
    在使用File之前,必须拥有一个File对象
    File file = new File("c:\data\input-file.txt");
    检测文件是否存在
    当你获得一个File对象之后,可以检测相应的文件是否存在。当文件不存在的时候,构造函数并不会执行失败。你已经准备好创建一个File了,对吧?
    通过调用exists()方法,可以检测文件是否存在
    File file = new File("c:\data\input-file.txt");
    boolean fileExists = file.exists();
    文件长度
    通过调用length()可以获得文件的字节长度
    File file = new File("c:\data\input-file.txt");
    long length = file.length();
    重命名或移动文件
    通过调用File类中的renameTo()方法可以重命名(或者移动)文件
    File file = new File("c:\data\input-file.txt");
    boolean success = file.renameTo(new File("c:\data\new-file.txt"));
    删除文件
    通过调用delete()方法可以删除文件
    File file = new File("c:\data\input-file.txt");
    boolean success = file.delete();
    delete()方法与rename()方法一样,返回布尔值表明是否成功删除文件,同样也会有相同的操作失败原因。
    检测某个路径是文件还是目录
    File对象既可以指向一个文件,也可以指向一个目录。可以通过调用isDirectory()方法,可以判断当前File对象指向的是文件还是目录。当方法返回值是true时,File指向的是目录,否则指向的是文件
    File file = new File("c:\data");
    boolean isDirectory = file.isDirectory();
    读取目录中的文件列表
    你可以通过调用list()或者listFiles()方法获取一个目录中的所有文件列表。list()方法返回当前File对象指向的目录中所有文件与子目录的字符串名称(译者注:不会返回子目录下的文件及其子目录名称)。listFiles()方法返回当前File对象指向的目录中所有文件与子目录相关联的File对象(译者注:与list()方法类似,不会返回子目录下的文件及其子目录)
    File file = new File("c:\data");
    String[] fileNames = file.list();
    File[] files = file.listFiles();

    Java IO: ByteArray和Filter
    简要概括Java IO中字节数组与过滤器的输入输出流,主要涉及以下4个类型的流:ByteArrayInputStream,ByteArrayOutputStream,FilterInputStream,FilterOutputStream。请注意,为了清晰,这里忽略了必要的异常处理。想了解更多异常处理的信息,请参考Java IO异常处理。
    ByteArrayInputStream
    ByteArrayInputStream允许你从字节数组中读取字节流数据,代码如下:
    byte[] bytes = ... //get byte array from somewhere.
    InputStream input = new ByteArrayInputStream(bytes);
    int data = input.read();
    while(data != -1) {
    //do something with data
    data = input.read();
    }
    input.close();
    如果数据存储在数组中,ByteArrayInputStream可以很方便地读取数据。如果你有一个InputStream变量,又想从数组中读取数据呢?很简单,只需要把字节数组传递给ByteArrayInputStream的构造函数,在把这个ByteArrayInputStream赋值给InputStream变量就可以了(译者注:InputStream是所有字节输入流流的基类,Reader是所有字符输入流的基类,OutputStream与Writer同理)。
    ByteArrayOutputStream
    ByteArrayOutputStream允许你以数组的形式获取写入到该输出流中的数据,代码如下:
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    //write data to output stream
    byte[] bytes = output.toByteArray();

    Java IO: Buffered和Data
    简要概括Java IO中Buffered和data的输入输出流,主要涉及以下4个类型的流:BufferedInputStream,BufferedOutputStream,DataInputStream,DataOutputStream。
    BufferedInputStream
    BufferedInputStream能为输入流提供缓冲区,能提高很多IO的速度。你可以一次读取一大块的数据,而不需要每次从网络或者磁盘中一次读取一个字节。特别是在访问大量磁盘数据时,缓冲通常会让IO快上许多。

    为了给你的输入流加上缓冲,你需要把输入流包装到BufferedInputStream中
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"));
    你可以给BufferedInputStream的构造函数传递一个值,设置内部使用的缓冲区设置大小(译者注:默认缓冲区大小8 * 1024B),就像这样:
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"), 8 * 1024);
    这个例子设置了8KB的缓冲区。最好把缓冲区大小设置成1024字节的整数倍,这样能更高效地利用内置缓冲区的磁盘。
    除了能够为输入流提供缓冲区以外,其余方面BufferedInputStream基本与InputStream类似。
    BufferedOutputStream
    与BufferedInputStream类似,BufferedOutputStream可以为输出流提供缓冲区。可以构造一个使用默认大小缓冲区的BufferedOutputStream(译者注:默认缓冲区大小8 * 1024B),代码如下:
    OutputStream output = new BufferedOutputStream(new FileOutputStream("c:\data\output-file.txt"));
    也可以手动设置缓冲区大小,代码如下:
    OutputStream output = new BufferedOutputStream(new FileOutputStream("c:\data\output-file.txt"), 8 * 1024);
    为了更好地使用内置缓冲区的磁盘,同样建议把缓冲区大小设置成1024的整数倍。
    除了能够为输出流提供缓冲区以外,其余方面BufferedOutputStream基本与OutputStream类似。唯一不同的时,你需要手动flush()方法确保写入到此输出流的数据真正写入到磁盘或者网络中。
    DataInputStream
    DataInputStream可以使你从输入流中读取Java基本类型数据,而不必每次读取字节数据。你可以把InputStream包装到DataInputStream中,然后就可以从此输入流中读取基本类型数据了,代码如下:
    DataInputStream input = new DataInputStream(new FileInputStream("binary.data"));
    int aByte = input.read();
    int anInt = input.readInt();
    float aFloat = input.readFloat();
    double aDouble = input.readDouble();//etc.
    input.close();
    当你要读取的数据中包含了int,long,float,double这样的基本类型变量时,DataInputStream可以很方便地处理这些数据。
    DataOutputStream
    DataOutputStream可以往输出流中写入Java基本类型数据
    DataOutputStream output = new DataOutputStream(new FileOutputStream("binary.data"));
    output.write(45);
    //byte data output.writeInt(4545);
    //int data output.writeDouble(109.123);
    //double data output.close();
    其他方面与DataInputStream类似,不再赘述。

    JAVA IO流(一)
    参考文章:http://ifeve.com/java-io-network/,并发编程网
    原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java IO教程
    Java的IO包主要关注的是从原始数据源的读取以及输出原始数据到目标媒介。以下是最典型的数据源和目标媒介:
    文件
    管道
    网络连接
    内存缓存
    System.in, System.out, System.error(注:Java标准输入、输出、错误输出)

    类InputStream, OutputStream, Reader 和Writer
    一个程序需要InputStream或者Reader从数据源读取数据,需要OutputStream或者Writer将数据写入到目标媒介中。
    InputStream和Reader与数据源相关联,OutputStream和writer与目标媒介相关联。
    Java IO的用途和特征
    Java IO中包含了许多InputStream、OutputStream、Reader、Writer的子类。这样设计的原因是让每一个类都负责不同的功能。这也就是为什么IO包中有这么多不同的类的缘故。各类用途汇总如下:

    文件访问
    网络访问
    内存缓存访问
    线程内部通信(管道)
    缓冲
    过滤
    解析
    读写文本 (Readers / Writers)
    读写基本类型数据 (long, int etc.)
    读写对象
    当通读过Java IO类的源代码之后,我们很容易就能了解这些用途。这些用途或多或少让我们更加容易地理解,不同的类用于针对不同业务场景。

    1、读写文件
    通过Java IO读文件
    如果你需要在不同端之间读取文件,你可以根据该文件是二进制文件还是文本文件来选择使用FileInputStream或者FileReader。这两个类允许你从文件开始到文件末尾一次读取一个字节或者字符,或者将读取到的字节写入到字节数组或者字符数组。你不必一次性读取整个文件,相反你可以按顺序地读取文件中的字节和字符。
    通过Java IO写文件
    如果你需要在不同端之间进行文件的写入,你可以根据你要写入的数据是二进制型数据还是字符型数据选用FileOutputStream或者FileWriter。你可以一次写入一个字节或者字符到文件中,也可以直接写入一个字节数组或者字符数据。数据按照写入的顺序存储在文件当中。
    文件和目录信息的获取
    有时候你可能需要读取文件的信息而不是文件的内容,举个例子,如果你需要知道文件的大小和文件的属性。对于目录来说也是一样的,比如你需要获取某个目录下的文件列表。通过File类可以获取文件和目录的信息。

    2、Java IO: 网络
    当两个进程之间建立了网络连接之后,他们通信的方式如同操作文件一样:利用InputStream读取数据,利用OutputStream写入数据。换句话来说,Java网络API用来在不同进程之间建立网络连接,而Java IO则用来在建立了连接之后的进程之间交换数据。

    基本上意味着如果你有一份能够对文件进行写入某些数据的代码,那么这些数据也可以很容易地写入到网络连接中去。你所需要做的仅仅只是在代码中利用InputStream替代FileInputStream进行数据的写入。因为FileInputStream是InputStream的子类,所以这么做并没有什么问题。(译者注:此处应该是OutputStream和FileOutputStream)

    实际上对于文件的读操作也类似,一个具有读取文件数据功能的组件,同样可以轻松读取网络连接中的数据。只需要保证读取数据的组件是基于InputStream而非FileInputStream即可。
    public class MyClass {

    public static void main(String[] args) {
    InputStream inputStream = new FileInputStream("c:\myfile.txt");
    process(inputStream);
    }

    public static void process(InputStream input) throws IOException {
    //do something with the InputStream
    }

    }
    在这个例子中,process()方法并不关心InputStream参数的输入流,是来自于文件还是网络(例子只展示了输入流来自文件的版本)。process()方法只会对InputStream进行操作。
    3、Java IO: 字节和字符数组
    原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java IO: 字节和字符数组
    内容列表

    从InputStream或者Reader中读入数组
    从OutputStream或者Writer中写数组
    在java中常用字节和字符数组在应用中临时存储数据。而这些数组又是通常的数据读取来源或者写入目的地。如果你需要在程序运行时需要大量读取文件里的内容,那么你也可以把一个文件加载到数组中。当然你可以通过直接指定索引来读取这些数组。但如果设计成为从InputStream或者Reader,而不是从数组中读取某些数据的话,你会用什么组件呢?


    从 InputStream 或 Reader中读取数组

    用ByteArrayInputStream或者CharArrayReader封装字节或者字符数组从数组中读取数据。通过这种方式字节和字符就可以以数组的形式读出了。

    样例如下
    byte[] bytes = new byte[1024];

     

    //把数据写入字节数组...

     

    InputStream input = new ByteArrayInputStream(bytes);

     

    //读取第一个字节

    int data = input.read();

    while(data != -1) {

    //操作数据

     

    //读下一个字节

    data = input.read();

    }
    以同样的方式也可以用于读取字符数组,只要把字符数组封装在CharArrayReader上就行了。

    通过 OutputStream 或者 Writer写数组

    同样,也可以把数据写到ByteArrayOutputStream或者CharArrayWriter中。你只需要创建ByteArrayOutputStream或者CharArrayWriter,把数据写入,就像写其它的流一样。当所有的数据都写进去了以后,只要调用toByteArray()或者toCharArray,所有写入的数据就会以数组的形式返回。

    样例如下:
    OutputStream output = new ByteArrayOutputStream();

     

    output.write("This text is converted to bytes".toBytes("UTF-8"));

     

    byte[] bytes = output.toByteArray();
    写字符数组也和此例子类似。只要把字符数组封装在CharArrayWriter上就可以了。
    4、流
    Java IO流是既可以从中读取,也可以写入到其中的数据流,流通常会与数据源、数据流向目的地相关联,比如文件、网络等等。流仅仅只是一个连续的数据流。
    Java IO流通常是基于字节或者基于字符的。字节流通常以“stream”命名,比如InputStream和OutputStream。字符流通常以“Reader”或者“Writer”命名。字符流能够读写字符(比如Latin1或者Unicode字符)。
    InputStream
    java.io.InputStream类是所有Java IO输入流的基类。如果你正在开发一个从流中读取数据的组件,请尝试用InputStream替代任何它的子类(比如FileInputStream)进行开发。这么做能够让你的代码兼容任何类型而非某种确定类型的输入流。

    然而仅仅依靠InputStream并不总是可行。如果你需要将读过的数据推回到流中,你必须使用PushbackInputStream,这意味着你的流变量只能是这个类型,否则在代码中就不能调用PushbackInputStream的unread()方法。

    通常使用输入流中的read()方法读取数据。read()方法返回一个整数,代表了读取到的字节的内容(译者注:0 ~ 255)。当达到流末尾没有更多数据可以读取的时候,read()方法返回-1。

    这是一个简单的示例:
    InputStream input = new FileInputStream("c:\data\input-file.txt");

    int data = input.read();

    while(data != -1){

    data = input.read();

    }
    OutputStream
    java.io.OutputStream是Java IO中所有输出流的基类。如果你正在开发一个能够将数据写入流中的组件,请尝试使用OutputStream替代它的所有子类。

    这是一个简单的示例:
    OutputStream output = new FileOutputStream("c:\data\output-file.txt");
    output.write("Hello World".getBytes());
    output.close();
    组合流
    你可以将流整合起来以便实现更高级的输入和输出操作。比如,一次读取一个字节是很慢的,所以可以从磁盘中一次读取一大块数据,然后从读到的数据块中获取字节。为了实现缓冲,可以把InputStream包装到BufferedInputStream中。代码示例:
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"));
    缓冲同样可以应用到OutputStream中。你可以实现将大块数据批量地写入到磁盘(或者相应的流)中,这个功能由BufferedOutputStream实现。

    缓冲只是通过流整合实现的其中一个效果。

    5、Reader
    Reader类是Java IO中所有Reader的基类。子类包括BufferedReader,PushbackReader,InputStreamReader,StringReader和其他Reader。
    这是一个简单的Java IO Reader的例子:
    Reader reader = new FileReader("c:\data\myfile.txt");
    int data = reader.read();
    while(data != -1){
    char dataChar = (char) data;
    data = reader.read();
    }
    请注意,InputStream的read()方法返回一个字节,意味着这个返回值的范围在0到255之间(当达到流末尾时,返回-1),Reader的read()方法返回一个字符,意味着这个返回值的范围在0到65535之间(当达到流末尾时,同样返回-1)。这并不意味着Reade只会从数据源中一次读取2个字节,Reader会根据文本的编码,一次读取一个或者多个字节。
    你通常会使用Reader的子类,而不会直接使用Reader。Reader的子类包括InputStreamReader,CharArrayReader,FileReader等等
    整合Reader与InputStream
    一个Reader可以和一个InputStream相结合。如果你有一个InputStream输入流,并且想从其中读取字符,可以把这个InputStream包装到InputStreamReader中。把InputStream传递到InputStreamReader的构造函数中:

    Reader reader = new InputStreamReader(inputStream);
    在构造函数中可以指定解码方式
    Writer
    Writer类是Java IO中所有Writer的基类。子类包括BufferedWriter和PrintWriter等等。这是一个Java IO Writer的例子:
    Writer writer = new FileWriter("c:\data\file-output.txt");
    writer.write("Hello World Writer");
    writer.close();
    同样,你最好使用Writer的子类,不需要直接使用Writer,因为子类的实现更加明确,更能表现你的意图。常用子类包括OutputStreamWriter,CharArrayWriter,FileWriter等。Writer的write(int c)方法,会将传入参数的低16位写入到Writer中,忽略高16位的数据。
    整合Writer和OutputStream
    与Reader和InputStream类似,一个Writer可以和一个OutputStream相结合。把OutputStream包装到OutputStreamWriter中,所有写入到OutputStreamWriter的字符都将会传递给OutputStream。这是一个OutputStreamWriter的例子:

    Writer writer = new OutputStreamWriter(outputStream);

    整合Reader和Writer
    和字节流一样,Reader和Writer可以相互结合实现更多更有趣的IO,工作原理和把Reader与InputStream或者Writer与OutputStream相结合类似。举个栗子,可以通过将Reader包装到BufferedReader、Writer包装到BufferedWriter中实现缓冲。以下是例子:
    Reader reader = new BufferedReader(new FileReader(...));
    Writer writer = new BufferedWriter(new FileWriter(...));
    6、IO 并发
    有时候你可能需要并发地处理输入和输出。换句话说,你可能有超过一个线程处理输入和产生输出。比如,你有一个程序需要处理磁盘上的大量文件,这个任务可以通过并发操作提高性能。又比如,你有一个web服务器或者聊天服务器,接收许多连接和请求,这些任务都可以通过并发获得性能的提升。
    如果你需要并发处理IO,这里有几个问题可能需要注意一下:
    在同一时刻不能有多个线程同时从InputStream或者Reader中读取数据,也不能同时往OutputStream或者Writer里写数据。你没有办法保证每个线程读取多少数据,以及多个线程写数据时的顺序。
    如果线程之间能够保证操作的顺序,它们可以使用同一个stream、reader、writer。比如,你有一个线程判断当前的输入流来自哪种类型的请求,然后将流数据传递给其他合适的线程做后续处理。当有序存取流、reader、writer时,这种做法是可行的。请注意,在线程之间传递流数据的代码应当是同步的。
    注意:在Java NIO中,你可以让一个线程读写多个“channel”。比如,你有很多网络连接处于开启状态,但是每个连接中都只有少量数据,类似于聊天服务器,可以让一个线程监视多个频道(连接)。
    7、Java IO: InputStream
    InputStream类是Java IO API中所有输入流的基类。InputStream子类包括FileInputStream,BufferedInputStream,PushbackInputStream等等。
    Java InputStream例子
    InputStream用于读取基于字节的数据,一次读取一个字节,这是一个InputStream的例子:
    InputStream inputstream = new FileInputStream("c:\data\input-text.txt");
    int data = inputstream.read();
    while(data != -1) {
    //do something with data...
    doSomethingWithData(data);
    data = inputstream.read();
    }
    inputstream.close();
    这个例子创建了FileInputStream实例。FileInputStream是InputStream的子类,所以可以把FileInputStream实例赋值给InputStream变量。
    read()
    read()方法返回从InputStream流内读取到的一个字节内容(译者注:0~255),例子如下:
    int data = inputstream.read();
    你可以把返回的int类型转化成char类型:
    char aChar = (char) data;
    InputStream的子类可能会包含read()方法的替代方法。比如,DataInputStream允许你利用readBoolean(),readDouble()等方法读取Java基本类型变量int,long,float,double和boolean。
    流末尾
    如果read()方法返回-1,意味着程序已经读到了流的末尾,此时流内已经没有多余的数据可供读取了。-1是一个int类型,不是byte或者char类型,这是不一样的。
    当达到流末尾时,你就可以关闭流了。
    read(byte[])
    InputStream包含了2个从InputStream中读取数据并将数据存储到缓冲数组中的read()方法,他们分别是:
    int read(byte[])
    int read(byte, int offset, int length)
    一次性读取一个字节数组的方式,比一次性读取一个字节的方式快的多,所以,尽可能使用这两个方法代替read()方法。
    read(byte[])方法会尝试读取与给定字节数组容量一样大的字节数,返回值说明了已经读取过的字节数。如果InputStream内可读的数据不足以填满字节数组,那么数组剩余的部分将包含本次读取之前的数据。记得检查有多少数据实际被写入到了字节数组中。
    read(byte, int offset, int length)方法同样将数据读取到字节数组中,不同的是,该方法从数组的offset位置开始,并且最多将length个字节写入到数组中。同样地,read(byte, int offset, int length)方法返回一个int变量,告诉你已经有多少字节已经被写入到字节数组中,所以请记得在读取数据前检查上一次调用read(byte, int offset, int length)的返回值。
    这两个方法都会在读取到达到流末尾时返回-1。
    这是一个使用InputStream的read(byte[])的例子:
    InputStream inputstream = new FileInputStream("c:\data\input-text.txt");
    byte[] data = new byte[1024];
    int bytesRead = inputstream.read(data);
    while(bytesRead != -1) {
    doSomethingWithData(data, bytesRead);
    bytesRead = inputstream.read(data);
    }
    inputstream.close();
    在代码中,首先创建了一个字节数组。然后声明一个叫做bytesRead的存储每次调用read(byte[])返回值的int变量,并且将第一次调用read(byte[])得到的返回值赋值给它。
    在while循环内部,把字节数组和已读取字节数作为参数传递给doSomethingWithData方法然后执行调用。在循环的末尾,再次将数据写入到字节数组中。
    你不需要想象出read(byte, int offset, int length)替代read(byte[])的场景,几乎可以在使用read(byte, int offset, int length)的任何地方使用read(byte[])。

    Java IO: OutputStream
    OutputStream类是Java IO API中所有输出流的基类。子类包括BufferedOutputStream,FileOutputStream等等。
    输出流和目标媒介
    输出流往往和某些数据的目标媒介相关联,比如文件,网络连接,管道等。
    Write(byte)
    write(byte)方法用于把单个字节写入到输出流中。OutputStream的write(byte)方法将一个包含了待写入数据的int变量作为参数进行写入。只有int类型的第一个字节会被写入,其余位会被忽略。
    OutputStream的子类可能会包含write()方法的替代方法。比如,DataOutputStream允许你利用writeBoolean(),writeDouble()等方法将基本类型int,long,float,double,boolean等变量写入。
    这是一个OutputStream的write()方法例子:
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    while(hasMoreData()) {
    int data = getMoreData();
    output.write(data);
    }
    output.close();
    这个例子首先创建了待写入的FileOutputStream。在进入while循环之后,循环的判断条件是hasMoreData()方法的返回值。hasMoreData()方法的实现不予展示,请把这个函数理解为:当有剩余可写数据时,返回true,否则返回false。
    write(byte[])
    OutputStream同样包含了将字节数据中全部或者部分数据写入到输出流中的方法,分别是write(byte[])和write(byte[], int offset, int length)。
    write(byte[])把字节数组中所有数据写入到输出流中。
    write(byte[], int offset, int length)把字节数据中从offset位置开始,length个字节的数据写入到输出流。
    flush()
    OutputStream的flush()方法将所有写入到OutputStream的数据冲刷到相应的目标媒介中。比如,如果输出流是FileOutputStream,那么写入到其中的数据可能并没有真正写入到磁盘中。即使所有数据都写入到了FileOutputStream,这些数据还是有可能保留在内存的缓冲区中。通过调用flush()方法,可以把缓冲区内的数据刷新到磁盘(或者网络,以及其他任何形式的目标媒介)中。
    close()
    当你结束数据写入时,需要关闭OutputStream。通过调用close()可以达到这一点。因为OutputStream的各种write()方法可能会抛出IO异常,所以你需要把调用close()的关闭操作方在finally块中执行。这是一个OutputStream调用close()的例子:
    OutputStream output = null;
    try{
    output = new FileOutputStream("c:\data\output-text.txt");
    while(hasMoreData()) {
    int data = getMoreData();
    output.write(data);
    }
    } finally {
    if(output != null) {
    output.close();
    }

    }


    Java IO: FileInputStream
    FileInputStream可以以字节流的形式读取文件内容。FileInputStream是InputStream的子类,这意味着你可以把FileInputStream当做InputStream使用(FileInputStream与InputStream的行为类似)。
    InputStream input = new FileInputStream("c:\data\input-text.txt");
    int data = input.read();while(data != -1) {
    //do something with data...
    doSomethingWithData(data);
    data = input.read();
    }
    input.close();
    FileInputStream的read()方法返回读取到的包含一个字节内容的int变量(译者注:0~255)。如果read()方法返回-1,意味着程序已经读到了流的末尾,此时流内已经没有多余的数据可供读取了,你可以关闭流。-1是一个int类型,不是byte类型,这是不一样的。
    FileInputStream也有其他的构造函数,允许你通过不同的方式读取文件

    其中一个FileInputStream构造函数取一个File对象替代String对象作为参数。
    File file = new File("c:\data\input-text.txt");
    InputStream input = new FileInputStream(file);
    至于你该采用参数是String对象还是File对象的构造函数,取决于你当前是否已经拥有一个File对象,也取决于你是否要在打开FileOutputStream之前通过File对象执行某些检查(比如检查文件是否存在)。


    Java IO: FileOutputStream
    FileOutputStream可以往文件里写入字节流,它是OutputStream的子类,所以你可以像使用OutputStream那样使用FileOutputStream。
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    while(moreData) {
    int data = getMoreData();
    output.write(data);
    }
    output.close();
    FileOutputStream的write()方法取一个包含了待写入字节(译者注:低8位数据)的int变量作为参数进行写入。
    FileOutputStream也有其他的构造函数,允许你通过不同的方式写入文件。
    文件内容的覆盖Override VS追加Appending
    当你创建了一个指向已存在文件的FileOutputStream,你可以选择覆盖整个文件,或者在文件末尾追加内容。通过使用不同的构造函数可以实现不同的目的。
    其中一个构造函数取文件名作为参数,会覆盖任何此文件名指向的文件。
    OutputStream output = new FileOutputStream("c:\data\output-text.txt");
    另外一个构造函数取2个参数:文件名和一个布尔值,布尔值表明你是否需要覆盖文件。这是构造函数的例子:
    OutputStream output = new FileOutputStream("c:\data\output-text.txt", true); //appends to file
    OutputStream output = new FileOutputStream("c:\data\output-text.txt", false); //overwrites file
    写入字节数组
    既然FileOutputStream是OutputStream的子类,所以你也可以往FileOutputStream中写入字节数组,而不需要每次都只写入一个字节。可以参考我的OutputStream教程查阅更多关于写入字节数组的信息。
    flush()
    当你往FileOutputStream里写数据的时候,这些数据有可能会缓存在内存中。在之后的某个时间,比如,每次都只有X份数据可写,或者FileOutputStream关闭的时候,才会真正地写入磁盘。当FileOutputStream没被关闭,而你又想确保写入到FileOutputStream中的数据写入到磁盘中,可以调用flush()方法,该方法可以保证所有写入到FileOutputStream的数据全部写入到磁盘中。

    Java IO: File
    java IO API中的FIle类可以让你访问底层文件系统,通过File类,你可以做到以下几点:
    检测文件是否存在
    读取文件长度
    重命名或移动文件
    删除文件
    检测某个路径是文件还是目录
    读取目录中的文件列表
    请注意:File只能访问文件以及文件系统的元数据。如果你想读写文件内容,需要使用FileInputStream、FileOutputStream或者RandomAccessFile。如果你正在使用Java NIO,并且想使用完整的NIO解决方案,你会使用到java.nio.FileChannel(否则你也可以使用File)。
    实例化一个java.io.File对象
    在使用File之前,必须拥有一个File对象
    File file = new File("c:\data\input-file.txt");
    检测文件是否存在
    当你获得一个File对象之后,可以检测相应的文件是否存在。当文件不存在的时候,构造函数并不会执行失败。你已经准备好创建一个File了,对吧?
    通过调用exists()方法,可以检测文件是否存在
    File file = new File("c:\data\input-file.txt");
    boolean fileExists = file.exists();
    文件长度
    通过调用length()可以获得文件的字节长度
    File file = new File("c:\data\input-file.txt");
    long length = file.length();
    重命名或移动文件
    通过调用File类中的renameTo()方法可以重命名(或者移动)文件
    File file = new File("c:\data\input-file.txt");
    boolean success = file.renameTo(new File("c:\data\new-file.txt"));
    删除文件
    通过调用delete()方法可以删除文件
    File file = new File("c:\data\input-file.txt");
    boolean success = file.delete();
    delete()方法与rename()方法一样,返回布尔值表明是否成功删除文件,同样也会有相同的操作失败原因。
    检测某个路径是文件还是目录
    File对象既可以指向一个文件,也可以指向一个目录。可以通过调用isDirectory()方法,可以判断当前File对象指向的是文件还是目录。当方法返回值是true时,File指向的是目录,否则指向的是文件
    File file = new File("c:\data");
    boolean isDirectory = file.isDirectory();
    读取目录中的文件列表
    你可以通过调用list()或者listFiles()方法获取一个目录中的所有文件列表。list()方法返回当前File对象指向的目录中所有文件与子目录的字符串名称(译者注:不会返回子目录下的文件及其子目录名称)。listFiles()方法返回当前File对象指向的目录中所有文件与子目录相关联的File对象(译者注:与list()方法类似,不会返回子目录下的文件及其子目录)
    File file = new File("c:\data");
    String[] fileNames = file.list();
    File[] files = file.listFiles();

    Java IO: ByteArray和Filter
    简要概括Java IO中字节数组与过滤器的输入输出流,主要涉及以下4个类型的流:ByteArrayInputStream,ByteArrayOutputStream,FilterInputStream,FilterOutputStream。请注意,为了清晰,这里忽略了必要的异常处理。想了解更多异常处理的信息,请参考Java IO异常处理。
    ByteArrayInputStream
    ByteArrayInputStream允许你从字节数组中读取字节流数据,代码如下:
    byte[] bytes = ... //get byte array from somewhere.
    InputStream input = new ByteArrayInputStream(bytes);
    int data = input.read();
    while(data != -1) {
    //do something with data
    data = input.read();
    }
    input.close();
    如果数据存储在数组中,ByteArrayInputStream可以很方便地读取数据。如果你有一个InputStream变量,又想从数组中读取数据呢?很简单,只需要把字节数组传递给ByteArrayInputStream的构造函数,在把这个ByteArrayInputStream赋值给InputStream变量就可以了(译者注:InputStream是所有字节输入流流的基类,Reader是所有字符输入流的基类,OutputStream与Writer同理)。
    ByteArrayOutputStream
    ByteArrayOutputStream允许你以数组的形式获取写入到该输出流中的数据,代码如下:
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    //write data to output stream
    byte[] bytes = output.toByteArray();

    Java IO: Buffered和Data
    简要概括Java IO中Buffered和data的输入输出流,主要涉及以下4个类型的流:BufferedInputStream,BufferedOutputStream,DataInputStream,DataOutputStream。
    BufferedInputStream
    BufferedInputStream能为输入流提供缓冲区,能提高很多IO的速度。你可以一次读取一大块的数据,而不需要每次从网络或者磁盘中一次读取一个字节。特别是在访问大量磁盘数据时,缓冲通常会让IO快上许多。

    为了给你的输入流加上缓冲,你需要把输入流包装到BufferedInputStream中
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"));
    你可以给BufferedInputStream的构造函数传递一个值,设置内部使用的缓冲区设置大小(译者注:默认缓冲区大小8 * 1024B),就像这样:
    InputStream input = new BufferedInputStream(new FileInputStream("c:\data\input-file.txt"), 8 * 1024);
    这个例子设置了8KB的缓冲区。最好把缓冲区大小设置成1024字节的整数倍,这样能更高效地利用内置缓冲区的磁盘。
    除了能够为输入流提供缓冲区以外,其余方面BufferedInputStream基本与InputStream类似。
    BufferedOutputStream
    与BufferedInputStream类似,BufferedOutputStream可以为输出流提供缓冲区。可以构造一个使用默认大小缓冲区的BufferedOutputStream(译者注:默认缓冲区大小8 * 1024B),代码如下:
    OutputStream output = new BufferedOutputStream(new FileOutputStream("c:\data\output-file.txt"));
    也可以手动设置缓冲区大小,代码如下:
    OutputStream output = new BufferedOutputStream(new FileOutputStream("c:\data\output-file.txt"), 8 * 1024);
    为了更好地使用内置缓冲区的磁盘,同样建议把缓冲区大小设置成1024的整数倍。
    除了能够为输出流提供缓冲区以外,其余方面BufferedOutputStream基本与OutputStream类似。唯一不同的时,你需要手动flush()方法确保写入到此输出流的数据真正写入到磁盘或者网络中。
    DataInputStream
    DataInputStream可以使你从输入流中读取Java基本类型数据,而不必每次读取字节数据。你可以把InputStream包装到DataInputStream中,然后就可以从此输入流中读取基本类型数据了,代码如下:
    DataInputStream input = new DataInputStream(new FileInputStream("binary.data"));
    int aByte = input.read();
    int anInt = input.readInt();
    float aFloat = input.readFloat();
    double aDouble = input.readDouble();//etc.
    input.close();
    当你要读取的数据中包含了int,long,float,double这样的基本类型变量时,DataInputStream可以很方便地处理这些数据。
    DataOutputStream
    DataOutputStream可以往输出流中写入Java基本类型数据
    DataOutputStream output = new DataOutputStream(new FileOutputStream("binary.data"));
    output.write(45);
    //byte data output.writeInt(4545);
    //int data output.writeDouble(109.123);
    //double data output.close();
    其他方面与DataInputStream类似,不再赘述。

    IO总结:
    一、步骤: 创建源 选择流 操作(读取|写出) 释放
    二、流

    节点流:离数据源|程序最近的流 处理流:装饰模式 提高性能增强功能
    1、 字节流:可以处理一切(纯文本、音频、视频等)
    1)、输入流 InputStream FileInputStream
    ByteArrayInputStream
    操作:read(字节数组)
    a)、中间容器 byte[] flush=new byte[长度]
    b)、接收长度 int len =0;
    c)、循环读取 while(-1!=(len=流.read(flush))){}
    d)、操作:输出、拷贝
    2)、输出流 OutputStream FileOutputStream
    ByteArrayOutputStream
    操作:write(字节数组,0,长度) 输出
    2、 字符流:只能处理纯文本
    1)、输入流:Reader FileReader
    操作:read(字符数组)
    a)、中间容器 char[] flush=new char[长度]
    b)、接收长度 int len =0;
    c)、循环读取 while(-1!=(len=流.read(flush))){}
    d)、操作:输出、拷贝
    2)、输出流:Writer FileWriter
    操作:write(字符数组,0,长度) 输出 1、 转换流:解码与编码字符集问题
    1)、输入流:InputStreamReader à解码
    2)、输出流:OutputStreamWriter—>编码
    2、缓冲流:提高性能
    1)、输入流:BufferedInputStream BufferedReader
    2)、输出流:BufferedOutputStream BufferedWriter
    3、处理数据+类型
    1)、基本+字符串:必须存在才能读取 读取与写出顺序一致
    a)、输入流:DataInputStream readXxx
    b)、输出流:DataOutputStream writeXxx
    2)、引用类型:Serializable transient
    a)、反序列化:ObjectInputStream readObject
    b)、序列化:ObjectOutputStream writeObject
    4、打印流: PrintStream
    5、System.in out err setIn setOut
    以下流使用新增方法不能发生多态
    1、 ByteArrayOutputStream: toByteArray()
    2、 BufferedReader: readLine()
    3、 BufferedWriter:newLine()
    4、 DataInputStream DataOutputStream
    5、 ObjectInputStream ObjectOutputStream
    6、 PrintStream

    三、重点
    一、步骤: 创建源 选择流 操作(读取|写出) 释放
    二、流

    节点流:离数据源|程序最近的流 处理流:装饰模式 提高性能增强功能
    1、 字节流:可以处理一切(纯文本、音频、视频等)
    1)、输入流 InputStream FileInputStream
    ByteArrayInputStream
    操作:read(字节数组)
    a)、中间容器 byte[] flush=new byte[长度]
    b)、接收长度 int len =0;
    c)、循环读取 while(-1!=(len=流.read(flush))){}
    d)、操作:输出、拷贝
    2)、输出流 OutputStream FileOutputStream
    ByteArrayOutputStream
    操作:write(字节数组,0,长度) 输出
    2、 字符流:只能处理纯文本
    1)、输入流:Reader FileReader
    操作:read(字符数组)
    a)、中间容器 char[] flush=new char[长度]
    b)、接收长度 int len =0;
    c)、循环读取 while(-1!=(len=流.read(flush))){}
    d)、操作:输出、拷贝
    2)、输出流:Writer FileWriter
    操作:write(字符数组,0,长度) 输出 1、 转换流:解码与编码字符集问题
    1)、输入流:InputStreamReader à解码
    2)、输出流:OutputStreamWriter—>编码
    2、缓冲流:提高性能
    1)、输入流:BufferedInputStream BufferedReader
    2)、输出流:BufferedOutputStream BufferedWriter
    3、处理数据+类型
    1)、基本+字符串:必须存在才能读取 读取与写出顺序一致
    a)、输入流:DataInputStream readXxx
    b)、输出流:DataOutputStream writeXxx
    2)、引用类型:Serializable transient
    a)、反序列化:ObjectInputStream readObject
    b)、序列化:ObjectOutputStream writeObject
    4、打印流: PrintStream
    5、System.in out err setIn setOut
    以下流使用新增方法不能发生多态
    1、 ByteArrayOutputStream: toByteArray()
    2、 BufferedReader: readLine()
    3、 BufferedWriter:newLine()
    4、 DataInputStream DataOutputStream
    5、 ObjectInputStream ObjectOutputStream
    6、 PrintStream

    三、重点

    四、操作
    0、打印文件|目录
    1、文件拷贝
    2、关闭流方法
    3、文件分割与合并(自学)

  • 相关阅读:
    面试题 面试技巧
    面试 11-02.ES6
    面试 11-00.JavaScript高级面试
    面试 11-01.ES6:模块化的使用和编译环境
    面试 10-01.页面性能优化
    面试 09-02.js运行机制:异步和单线程
    面试 10-02.前端错误监控
    选择屏幕-SELECTION-SCREEN(二)
    ◆◆0如何创建代码模板
    行选择交互事件
  • 原文地址:https://www.cnblogs.com/qull/p/6612259.html
Copyright © 2011-2022 走看看