Java IO简介
转自http://tutorials.jenkov.com/java-io/overview.html
Java IO是Java附带的API,用于读取和写入数据(输入和输出)。大多数应用程序需要处理一些输入并根据该输入生成一些输出。Java IO API位于Java IO包(java.io
)中,Java IO包主要关注文件,网络流,内部存储器缓冲区等的输入和输出。但是,Java IO包不包含用于打开网络通信所必需的网络套接字的类。为此,您需要使用Java Networking API。一旦打开了套接字(网络连接),就可以通过Java IO InputStream
和OutputStream
类来读取和写入数据;Java还包含另一个名为Java NIO的 IO API 。它包含与Java IO和Java Networking API大致相同的类,但Java NIO可以在非阻塞模式下工作。在某些情况下,非阻塞IO可以比阻塞IO提供更大的性能提升。
IO Streams是Java IO中的核心概念。流是概念上无穷无尽的数据流。可以从流中读取或写入。流连接到数据源或数据目标。Java IO中的流可以是基于字节的(读取和写入字节),也可以是基于字符的(读取和写入字符)。
需要从某个源读取数据的程序需要一个InputStream
或一个Reader。需要将数据写入某个目的地的程序需要OutputStream
或Writer
一个InputStream
或Reader
链接到数据源。一个OutputStream
或Writer
链接到数据的目的地。
Java的IO包含很多子类InputStream
,OutputStream
,Reader
和Writer
类。原因是,所有这些子类都在解决各种不同的目的:
- 文件访问
- 网络访问
- 内部缓冲区访问
- 线程间通信(管道)
- 缓冲
- 过滤
- 解析
- 读和写文本(Readers / Writers)
- 读写原始数据(long,int等)
- 读和写对象
Java IO类概述表
Java IO FIles:
文件是java应用中数据的常见源或目标,如果需要从一端读取文件到另一端,可以使用 FileInputStream
或 FileReader
取决于是否要将文件读取为二进制或文本数据。这两个类允许从文件的开头到结尾一次读取一个字节或一个字符的文件,或者将字节读取到数组中,byte
或者char
从文件的开头到结尾再次读取。不必读取整个文件,但只能按文件中存储的顺序读取字节和字符。如果需要跳转文件并从此处和那里只读取部分文件,您可以使用 RandomAccessFile。
如果需要将文件从一端写入另一端,则可以使用 FileOutputStream
或 FileWriter
取决于是否需要写入二进制数据或字符。可以从文件的开头到结尾一次写一个字节或字符,或者写byte
和的数组char
。数据按照写入顺序依次存储在文件中。如果需要跳过一个文件并在不同的地方写入它,例如附加到文件的末尾,你可以使用RandomAccessFile
。
通过RandomAccessFile
类随机访问带有Java IO的文件,随机访问并不意味着从真正随机的地方读取或写入。它只是意味着可以以任何方式跳过文件并同时读取或写入文件。没有强制执行特定的访问顺序。这样就可以覆盖现有文件的一部分,附加到它,从中删除,当然也可以从文件读取,无论需要从哪里读取。
有时可能需要访问有关文件而非其内容的信息。如需要知道文件的文件大小或文件属性。对于目录也是如此。可能希望获取给定目录中所有文件的列表。文件和目录信息都可以通过File
获得。
Java IO Pipes :
Java IO中的pipes提供了在同一JVM中运行的两个线程进行通信的能力。因此,管道也可以是数据的来源或目的地。不能使用管道与不同JVM(不同进程)中的线程进行通信。Java中的管道概念不同于Unix / Linux中的管道概念,他们在不同地址空间中运行的两个进程可以通过管道进行通信。但在Java中,通信方必须在同一进程中运行,并且应该是不同的线程。
使用Java IO创建管道是通过PipedOutputStream
和 PipedInputStream
类完成的。PipedInputStream
应该连接到 PipedOutputStream
。PipedOutputStream
一个线程写入的数据可以PipedInputStream
通过另一个线程从连接中读取 。
import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipeExample { public static void main(String [] args)throws IOException { final PipedOutputStream output = new PipedOutputStream(); final PipedInputStream input = new PipedInputStream(output); Thread thread1 = new Thread(new Runnable(){ @Override public void run(){ try { output.write(“Hello world,pipe!”.getBytes()); } catch(IOException e){ } } }); Thread thread2 = new Thread(new Runnable(){ @Override public void run(){ try { int data = input.read(); while(data!= -1){ System.out.print((char)data) ; data = input.read(); } } catch(IOException e){ } } }); thread1.start(); thread2.start(); } }
还可以使用其connect()
方法连接两个管道流。双方 PipedInputStream
并PipedOutputStream
有一个connect()
可连接一个到另一个方法。在使用两个连接的管道流时,将一个流传递给一个线程,将另一个流传递给另一个线程。流上的read()和write()调用被阻塞,这意味着如果您试图同时使用相同的线程进行读写,这可能导致线程本身死锁。
除了管道之外,在同一个JVM中,线程还可以通过许多其他方式进行通信。实际上,线程更经常交换完整的对象,而不是原始的字节数据。但是——如果需要在线程之间交换原始字节数据,则可以使用Java IO的管道。
Java IO Networking :
Java中联网的细节部分超出了本Java IO的范围。但是,由于网络连接是公共的数据源或数据目的地,并且由于使用Java IO API通过网络连接进行通信。一旦在两个进程之间建立了网络连接,它们就会像与文件通信一样通过网络连接进行通信:使用InputStream读取数据,使用OutputStream写入数据。换句话说,当Java Networking API用于在进程之间建立网络连接时,Java IO用于在建立连接后在进程之间交换数据。
如果有能够将某些内容写入文件的代码,那么可以很容易地将其写入到网络连接中。所需要的是组件完成编写依赖于OutputStream而不是FileOutputStream。因为FileOutputStream是OutputStream的子类。
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上工作。
Java IO Byte & Char Arrays :
在Java中,字节数组和字符数组通常用于在应用程序内部临时存储数据。因为这样的数组也是数据的一个公共源或目标。如果需要在程序运行时大量访问该文件的内容,也可以将文件加载到数组中。可以通过索引访问这些数组。但是,如果您有一个组件被设计为从InputStream或Reader而不是数组中读取某些特定数据,要使这样的组件从数组中读取数据,必须将字节或字符数组包装在ByteArrayInputStream或CharArrayReader中。这样,数组中可用的字节或字符就可以通过包装流或读取器进行读取。
byte[] bytes = new byte[1024]; //write data into byte array... InputStream input = new ByteArrayInputStream(bytes); //read first byte int data = input.read(); while(data != -1) { //do something with data //read next byte data = input.read(); }
对char数组做同样的处理与此示例非常相似。将char数组包装在CharArrayReader中就可以了。
也可以将数据写入ByteArrayOutputStream或CharArrayWriter。所要做的就是创建ByteArrayOutputStream或CharArrayWriter,并将您的数据写入它,就像您写入其他流或writer一样。写入所有数据后,只需调用toByteArray()或toCharArray()方法,所有写入的数据都以数组的形式返回。
ByteArrayOutputStream output = new ByteArrayOutputStream(); output.write("This text is converted to bytes".getBytes("UTF-8")); byte[] bytes = output.toByteArray();
对char数组做同样的处理与此示例非常相似。只需将char数组封装在CharArrayWriter中,就可以了。
Java IO:System.in,System.out和System.error