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、文件分割与合并(自学)

  • 相关阅读:
    Java程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/qull/p/6612259.html
Copyright © 2011-2022 走看看