原文地址:http://249326109.iteye.com/blog/1321915
Java 的10 流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作, Java 中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为"流" (stream) ,通过流的方式允许Java 程序使用相同的方式来访问不同的输入/输出源。stream 是从起源(source) 到接收(sink) 的有序数据。
流按照相对于内存的方向分为输入流和输出流,也可以按照读写的单位分为字节流和字符流,而且还可以根据流的使用不同分为节点流和封装流(采用了典型的装饰器的设计模式,使得IO流用起来非常灵活)。
以下来自core java:
In the Java API, an object from which we can read a sequence of bytes is called an input stream. An object to which we can write a sequence of bytes is called an output stream. These sources and destinations of byte sequences can be—and often are—files, but they can also be network connections and even blocks of memory. The abstract classes InputStream and OutputStream form the basis for a hierarchy of input/output (I/O) classes.
Because byte-oriented streams are inconvenient for processing information stored in Unicode (recall that Unicode uses multiple bytes per character), there is a separate hierarchy of classes for processing Unicode characters that inherit from the abstract Reader and Writer classes. These classes have read and write operations that are based on two-byte Unicode code units rather than on single-byte characters.
以下是字节流和字符流的层次图。
由上图可看出,java IO 体系中有访问文件,数组,管道和字符串的节点流;以及缓冲流,对象流,推回输入流,特殊流
等高层处理流;还有两个转换流。
下面程序分别使用了字节和字符读取文件并复制一份,并且与buffered版本进行了对比。
- package stream;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.FileReader;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.Writer;
- public class Streamtest {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- FileInputStream fileInputStream = null;
- FileOutputStream fileOutputStream = null;
- FileReader fReader = null;
- FileWriter fWriter = null;
- BufferedInputStream bis = null;
- BufferedOutputStream bos = null;
- BufferedReader br=null;
- BufferedWriter bw=null;
- //stream
- long byteStart =System.currentTimeMillis();
- try {
- fileInputStream = new FileInputStream("三国演义.txt");
- fileOutputStream = new FileOutputStream("三国演义副本一.txt");
- int hasRead = 0;
- byte[] buf = new byte[10];
- while ((hasRead = fileInputStream.read(buf)) > 0) {
- fileOutputStream.write(buf, 0, hasRead);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (fileInputStream != null)
- fileInputStream.close();
- if (fileOutputStream != null)
- fileOutputStream.close();
- long byteEnd=System.currentTimeMillis();
- System.out.println("字节复制完毕!花费"+(byteEnd-byteStart)+" ms.");
- }
- //buffered stream
- long bufferedByteStart =System.currentTimeMillis();
- try {
- fileInputStream = new FileInputStream("三国演义.txt");
- fileOutputStream = new FileOutputStream("buffered三国演义副本一.txt");
- bis=new BufferedInputStream(fileInputStream);
- bos=new BufferedOutputStream(fileOutputStream);
- int hasRead = 0;
- byte[] buf = new byte[10];
- while ((hasRead = bis.read(buf)) > 0) {
- bos.write(buf, 0, hasRead);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (bis != null)
- bis.close();
- if (bos != null)
- bos.close();
- long bufferedByteEnd=System.currentTimeMillis();
- System.out.println("buffered字节复制完毕!花费"+(bufferedByteEnd-bufferedByteStart)+" ms.");
- }
- //reader writer
- long charStart=System.currentTimeMillis();
- try {
- fReader = new FileReader("三国演义.txt");
- fWriter = new FileWriter("三国演义副本二.txt");
- char[] cbuf = new char[10];
- int hasRead = 0;
- while ((hasRead = fReader.read(cbuf)) > 0) {
- fWriter.write(cbuf, 0, hasRead);
- }
- } catch (IOException e) {
- // TODO: handle exception
- } finally {
- if (fReader != null)
- fReader.close();
- if (fWriter != null)
- fWriter.close();
- long charEnd=System.currentTimeMillis();
- System.out.println("字符复制完毕! 花费"+(charEnd-charStart)+" ms.");
- }
- //buffered reader writer
- long bufferedCharStart=System.currentTimeMillis();
- try {
- fReader = new FileReader("三国演义.txt");
- fWriter = new FileWriter("buffered三国演义副本二.txt");
- br=new BufferedReader(fReader);
- bw=new BufferedWriter(fWriter);
- char[] cbuf = new char[10];
- int hasRead = 0;
- while ((hasRead = br.read(cbuf)) > 0) {
- bw.write(cbuf, 0, hasRead);
- }
- } catch (IOException e) {
- // TODO: handle exception
- } finally {
- if (br != null)
- br.close();
- if (bw != null)
- bw.close();
- long bufferedCharEnd=System.currentTimeMillis();
- System.out.println("buffered字符复制完毕!花费"+(bufferedCharEnd-bufferedCharStart)+" ms.");
- }
- }
- }
package stream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; public class Streamtest { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; FileReader fReader = null; FileWriter fWriter = null; BufferedInputStream bis = null; BufferedOutputStream bos = null; BufferedReader br=null; BufferedWriter bw=null; //stream long byteStart =System.currentTimeMillis(); try { fileInputStream = new FileInputStream("三国演义.txt"); fileOutputStream = new FileOutputStream("三国演义副本一.txt"); int hasRead = 0; byte[] buf = new byte[10]; while ((hasRead = fileInputStream.read(buf)) > 0) { fileOutputStream.write(buf, 0, hasRead); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream != null) fileInputStream.close(); if (fileOutputStream != null) fileOutputStream.close(); long byteEnd=System.currentTimeMillis(); System.out.println("字节复制完毕!花费"+(byteEnd-byteStart)+" ms."); } //buffered stream long bufferedByteStart =System.currentTimeMillis(); try { fileInputStream = new FileInputStream("三国演义.txt"); fileOutputStream = new FileOutputStream("buffered三国演义副本一.txt"); bis=new BufferedInputStream(fileInputStream); bos=new BufferedOutputStream(fileOutputStream); int hasRead = 0; byte[] buf = new byte[10]; while ((hasRead = bis.read(buf)) > 0) { bos.write(buf, 0, hasRead); } } catch (IOException e) { e.printStackTrace(); } finally { if (bis != null) bis.close(); if (bos != null) bos.close(); long bufferedByteEnd=System.currentTimeMillis(); System.out.println("buffered字节复制完毕!花费"+(bufferedByteEnd-bufferedByteStart)+" ms."); } //reader writer long charStart=System.currentTimeMillis(); try { fReader = new FileReader("三国演义.txt"); fWriter = new FileWriter("三国演义副本二.txt"); char[] cbuf = new char[10]; int hasRead = 0; while ((hasRead = fReader.read(cbuf)) > 0) { fWriter.write(cbuf, 0, hasRead); } } catch (IOException e) { // TODO: handle exception } finally { if (fReader != null) fReader.close(); if (fWriter != null) fWriter.close(); long charEnd=System.currentTimeMillis(); System.out.println("字符复制完毕! 花费"+(charEnd-charStart)+" ms."); } //buffered reader writer long bufferedCharStart=System.currentTimeMillis(); try { fReader = new FileReader("三国演义.txt"); fWriter = new FileWriter("buffered三国演义副本二.txt"); br=new BufferedReader(fReader); bw=new BufferedWriter(fWriter); char[] cbuf = new char[10]; int hasRead = 0; while ((hasRead = br.read(cbuf)) > 0) { bw.write(cbuf, 0, hasRead); } } catch (IOException e) { // TODO: handle exception } finally { if (br != null) br.close(); if (bw != null) bw.close(); long bufferedCharEnd=System.currentTimeMillis(); System.out.println("buffered字符复制完毕!花费"+(bufferedCharEnd-bufferedCharStart)+" ms."); } } }
结果可以看出,buffered封装后却是提高了效率。
- 字节复制完毕!花费1020 ms.
- buffered字节复制完毕!花费21 ms.
- 字符复制完毕! 花费90 ms.
- buffered字符复制完毕!花费30 ms.
字节复制完毕!花费1020 ms. buffered字节复制完毕!花费21 ms. 字符复制完毕! 花费90 ms. buffered字符复制完毕!花费30 ms.
关于buffer:首先要知道什么是缓冲,buffering,如CPU和硬盘之间的关系,寄存器或内存就是作为缓冲,如果没有缓冲,当CPU要向硬盘存取数据时,只能直接存取,导致效率低下。
比如总共要读取10个字符,每次用一个,那只能每次从硬盘读一个用一个,如果有缓冲,就能先直接缓冲10个,然后再从缓冲中读一个用一个,出于硬件条件等的天生受限,使用buffering会大大提高效率。
PrintStream 和 PrintWriter
PrintStream是OutputStream的子类,PrintWriter是Writer的子类,两者处于对等的位置上,所以它们的API是非常相似的。PrintWriter实现了PritnStream的所有print方法。对于PrintStream,所有println方法都在内部调用相应的print方法,比如println(char x)的方法体就是调用print(x);再写入一个平台相关的换行符。PrintStream构建时会在内部new一个BufferedWriter,所有print方法都在内部调用这个Writer的write方法(write(String)或write(char[]))——对于print(char[]),直接调用write(char[]);对于其他的print方法,先用String.valueOf获得参数的字符串表示,然后调用write(String)。
对于PrintWriter,所有println方法也都在内部调用print方法,print方法调用write方法。传入OutputStream时,PrintWriter会在内部构造一个BufferedWriter;而传入Writer时,PrintStream内部直接使用该Writer,此时PrintWriter是否进行了缓冲全看该Writer。
所以,对于使用print系列方法的场合,二者没什么区别。
但是,PrintStream是字节流,它有处理raw byte的方法,write(int)和write(byte[],int,int);PrintWriter是字符流,它没有处理raw byte的方法。PrintStream和PrintWriter的auto flushing机制有点不同,前者在输出byte数组、调用println方法、输出换行符或者byte值10(即\n)时自动调用flush方法,后者仅在调用println方法时发生auto flushing。
相关推荐
Java I/O(输入/输出)系统是Java编程语言中用于处理数据流的重要组成部分,它允许程序与外部资源如文件、网络、硬件设备等进行交互。深入理解Java I/O的工作机制对于开发高效、可靠的系统至关重要。以下是对Java I/...
9. **NIO(非阻塞I/O)**: Java NIO提供了`java.nio.file`包,包含`Path`接口和`Files`工具类,提供更现代的文件操作API。如`Files#exists(Path path)`、`Files#createFile(Path path)`等。 10. **Path接口**: ...
6. **输入/输出(I/O)**:Java的I/O流系统包括字符流和字节流,以及用于文件操作、网络通信和对象序列化的API。学会使用BufferedReader、FileWriter等类进行文件操作,是开发中常见的需求。 7. **网络编程**:Java...
3. **流(Stream)**:Java的I/O流系统用于读取和写入数据,包括文件、网络、内存等。在抽奖软件中,流可能被用来读取参与者名单或者保存和加载抽奖结果。例如,使用FileInputStream和FileOutputStream处理文件,...
- **NIO**:非阻塞I/O,通道(Channel)和缓冲区(Buffer)的使用。 5. **网络编程** - **Socket编程**:TCP和UDP的原理及实现。 - **HTTP协议**:了解HTTP的基本请求和响应模型。 6. **JVM** - **类加载机制*...
- **NIO连接器**:提供了非阻塞I/O,提升了高并发场景下的性能。 - **Jasper升级**:JSP编译器Jasper升级到2.3.0,支持JSP 2.2规范,提高了JSP的处理效率。 2. **Tomcat 8**: - **Servlet 3.1** 支持:增加了...
了解非阻塞I/O(NIO)的概念和应用,能提升程序的效率。 6. **多线程**:学习如何创建和管理线程,理解同步机制,如synchronized关键字、wait()、notify()等。通过习题,可以实践多线程编程,解决并发问题。 7. **...
4. 文件和I/O流操作:文件读写、缓冲流、对象序列化等。 5. 多线程编程:线程同步、线程池、并发工具类等。 6. 网络编程:Socket通信、HTTP请求等。 7. Java异常处理:自定义异常、异常链、try-catch-finally语句块...
Servlet 3.1最大的改进是实现了非阻塞式的I/O通信。这使得性能得到巨大的改进,数据可以通过ReadListener和WriteListener接口以异步的方式进行管理。 Servlet 3.1的第二大改进是HTTP协议的升级。它允许客户端指定...
Eclipse 是一个强大的开源集成开发环境(IDE),尤其在Java编程领域中广泛应用。为了提高开发效率,掌握Eclipse的快捷键至关重要。以下是一些常用的Eclipse快捷键,它们可以帮助程序员快速编写、编辑、调试和管理...
3. **文件I/O操作**:记事本需要读取和保存文件,这就涉及到Java的File、FileInputStream、FileOutputStream类以及BufferedReader和PrintWriter等流类的使用。 4. **事件监听**:在Java GUI应用中,用户与界面的...
每种语言都有其特性和优势,例如,Java的Spring框架提供企业级服务,Python的Django和Flask提供快速开发环境,Node.js则擅长异步I/O处理。 4. **数据库**:数据存储是任何应用不可或缺的部分。MySQL、PostgreSQL、...
5. **NIO_TEST**:这可能是一些与Java NIO(非阻塞I/O)相关的测试代码或实验,MINA是基于Java NIO构建的,因此理解NIO对于使用MINA至关重要。 6. **MINA使用手记[1] _files**:这可能是一个文件夹,包含与第一篇...
同样,`dojo.io.*`和`dojo.widget.*`代表了所有与I/O和部件相关的模块,这样可以确保只有所需的代码被加载到页面中。 在实际应用中,Dojo提供了预整合包,以满足不同用户的需求。例如,Ajax版和Widget版分别针对...
* 主机一配置要求包括:CPU类型、处理器个数、TPCC值要求、内存、内置磁盘容量、系统带宽、I/O带宽、实际配置系统I/O插槽、内置DVD-ROM、快速以太网口、多模光纤网卡、FC光纤通道卡等 * 操作系统:UNIX,支持中文...
MINA的核心设计原则是事件驱动和非阻塞I/O,这使得它在处理大量并发连接时表现出色。其API设计简洁,易于理解和使用,支持多种传输协议,包括TCP、UDP以及NIO(New I/O)。 在MINA中,一个基本的网络应用通常由以下...
5. **优化性能**:如果"DocMerger.cs"考虑了性能,那么它可能会实现一些优化策略,比如批量操作、延迟加载或者使用内存流来减少磁盘I/O。 6. **设计模式**:这个类可能遵循单一职责原则,使得合并功能封装在一个...
o m m u n i c a t i n go b j e c t)的重复模式。这些模式解决特定的设计问题,使面向对象设计更灵活、优雅,最终复用性更 好。它们帮助设计者将新的设计建立在以往工作的基础上,复用以往成功的设计方案。 一个...