Java IO详解(转)
IO是Java及众多编程语言很重要的一块,同时很多程序的瓶颈和耗时操作也都在IO这块。
一、简介
IO操作面临很多问题,信息量的巨大,网络的环境等等,因为IO不仅仅是对本地文件、目录的操作,有时对二进制流、还有一部分是网络方面的资源,所以多种原因直接造成IO操作无疑是耗时且复杂多变的。Java对IO的支持是个不断的演变过程,经过了很多的优化,直到JDK1.4以后,才趋于稳定,在JDK1.4中,加入了nio类,解决了很多性能问题,虽然我们有足够的理由不去了解关于Java IO以前的情况,但是为了学好现在的类,我们还是打算去研究下,通过掌握类的优化情况来彻底理解IO的机制!Java IO主要主要在java.io包下,分为四大块近80个类:
1、基于字节操作的I/O接口:InputStream和OutputStream
2、基于字符操作的I/O接口:Writer和Reader
3、基于磁盘操作的I/O接口:File
4、基于网络操作的I/O接口:Socket(不在java.io包下)
影响IO性能的无非就是两大因素:数据的格式及存储的方式,前两类主要是数据格式方面的,后两个类是存储方式方面的:本地和网络。所以策划好这两个方面的活动,有助于我们合理使用IO。
二、基于字节的I/O操作(InputStream和OutputStream)
我们先来看看类图:
图1
图2
二者类似,我只详细讲解InputStream类,OutputStream留给大家自己去学习。InputStream类是个抽象类,里面核心的方法就是read()、read(byte b[])、read(byte b[], int off, int len),这三个方法是用于读取数据的底层的方法,他们可以用来读取一下这些类型的数据:
A. 字节数组
B. String对象
C. 文件
D. 管道,从一端进入,从另一端输出
E. 流
F. internet资源
每一种数据源都有相应的InputStream子类,因为InputStream是个处于顶层的类,用来处理各种数据源的类都继承了InputStream类,我们来看看这些类:
ByteArrayInputStream:处理字节数组的类,允许将内存的缓冲区当做InputStream使用。
StringBufferInputStream:将String转换成InputStream,内部实现用的是StringBuffer。
FileInputStream:从文件中读取数据。
PipedInputStream:用于从管道中读取数据。
SequenceInputStream:将多个流对象转化成一个InputStream。
FilterInputStream:装饰器类,为其它InputStream类提供功能。
做过关于IO操作的读者知道,我们很少单独使用哪个类来实现IO操作,平时都是几个类合起来使用,这其实体现了一种装饰器模式(详见:http://blog.csdn.net/zhangerqing)的思想,在后面的分析中我们会详细的分析。从上面的图1中我们可以看出,FilterInputStream虽说是Inputstream的子类,但它依然是BufferedInputStream、DataInputStream、LineNumberInputStream、PushbackInputStream类的父类,这四个类分别提供了最贴近我们程序员使用的方法,如:readInt() 、readInt()、readInt()等等。对于IO操作,不管是磁盘还是网络,最终都是对字节的操作,而我们平时写的程序都是字符形式的,所以在传输的过程中需要进行转换。在字符到字节的转换过程中,我们需要用到一个类:InputStreamReader。
三、基于字符的I/O操作(Writer和Reader)
图3
图4
Writer和Reader操作的目的就是操作字符和不是字节,和InputStream和OutputStream配合增加IO效果。通过InputStreamReader和OutputStreamReader可以进行字节和字符的转换,设计Writer和Reader的目的是国际化,使IO操作支持16位的Unicode。我把它们单独的画出来,因为要是全画的话,太大了放不下,有兴趣的TX可以在rational rose中导入其带的JDK类图看看,很过瘾的!
四、基于磁盘的I/O操作(File)
五、基于网络的I/O操作(Socket)
六、NIO
四-六部分由于时间关系,还没有整理完,后续会补出来!
七、经典IO操作
1、缓冲输入文件。
- import java.io.BufferedReader;
- import java.io.FileReader;
- public class InputStreamTest {
- public static String read(String filename) throws Exception {
- BufferedReader br = new BufferedReader(new FileReader(filename));
- String s;
- StringBuffer sb = new StringBuffer();
- while ((s = br.readLine()) != null) {
- sb.append(s + "\n");
- }
- br.close();
- return sb.toString();
- }
- public static void main(String[] args) throws Exception {
- System.out.println(read("src/InputStreamTest.java"));
- }
- }
这段代码是从磁盘读入InputStreamTest.java文件,然后转换成字符串。输出就是将源文件原样输出。
2、从内存中读取。
- import java.io.StringReader;
- public class MemoryInput {
- public static void main(String[] args) throws Exception {
- StringReader in = new StringReader(
- InputStreamTest.read("src/MemoryInput.java"));
- int c;
- while ((c = in.read()) != -1)
- System.out.println((char) c);
- }
- }
read返回的是int类型的数据,所以在输出语句中用char做了强类型转换。该程序将一个一个的输出字符。
3、基本的文件输出。
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.FileWriter;
- import java.io.PrintWriter;
- import java.io.StringReader;
- public class BasicFileOutput {
- static String file = "basie.out";
- public static void main(String[] args) throws Exception {
- BufferedReader in = new BufferedReader(new StringReader(
- InputStreamTest.read("src/BasicFileOutput.java")));
- PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
- file)));
- int lineCount = 1;
- String s;
- while ((s = in.readLine()) != null) {
- out.println(lineCount++ + ": " + s);
- }
- out.close();
- System.out.println(InputStreamTest.read(file));
- }
- }
输出:
1: import java.io.BufferedReader;
2: import java.io.BufferedWriter;
3: import java.io.FileWriter;
…
4、RandomAccessFile
RandomAccessFile被我们称为”自我独立的类”,因为它独立于我们前面说的IO类,与InputStream和OutputStream没什么关系,除了实现了DataOutput, DataInput两个接口外。所有方法都是重新编写,而且很多都是native方法,我们来看个例子,了解下这个类:
5、管道流
八、标准I/O
就是我们最原始的使用的从控制台输入或者输出的那些类和方法,如System.in、System.out等。
- public class StandardIO {
- public static void main(String[] args) throws IOException {
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
- String s;
- while ((s = in.readLine()) != null && s.length() != 0)
- System.out.println(s);
- }
- }
System.in返回的是未经包装的InputStream对象,所以需要进行装饰,经InputStreamReader转换为Reader对象,放入BufferedReader的构造方法中。除此之外,System.out和System.err都是直接的PriintStream对象,可直接使用。我们也可以使用java.util包下的Scanner类来代替上述程序:
- public class StandardIO {
- public static void main(String[] args) throws IOException {
- Scanner in = new Scanner(System.in);
- String s;
- while((s = in.next()) != null && s.length() != 0){
- System.out.println(s);
- }
- }
- }
九、性能分析及总结
1、一个文件读写工具类。
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.ArrayList;
- import java.util.Arrays;
- /**
- * 一个非常实用的文件操作类 . 2012-12-19
- *
- * @author Bruce Eckel , edited by erqing
- *
- */
- public class TextFile extends ArrayList<String> {
- private static final long serialVersionUID = -1942855619975438512L;
- // Read a file as a String
- public static String read(String filename) {
- StringBuilder sb = new StringBuilder();
- try {
- BufferedReader in = new BufferedReader(new FileReader(new File(
- filename).getAbsoluteFile()));
- String s;
- try {
- while ((s = in.readLine()) != null) {
- sb.append(s);
- sb.append("\n");
- }
- } finally {
- in.close();
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return sb.toString();
- }
- // Write a single file in one method call
- public static void write(String fileName, String text) {
- try {
- PrintWriter out = new PrintWriter(
- new File(fileName).getAbsoluteFile());
- try {
- out.print(text);
- } finally {
- out.close();
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- // Read a file,spilt by any regular expression
- public TextFile(String fileName, String splitter) {
- super(Arrays.asList(read(fileName).split(splitter)));
- if (get(0).equals(""))
- remove(0);
- }
- // Normally read by lines
- public TextFile(String fileName) {
- this(fileName, "\n");
- }
- public void write(String fileName) {
- try {
- PrintWriter out = new PrintWriter(
- new File(fileName).getAbsoluteFile());
- try {
- for (String item : this)
- out.println(item);
- } finally {
- out.close();
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- // test,I have generated a file named data.d at the root
- public static void main(String[] args) {
- /* read() test */
- System.out.println(read("data.d")); // testing is OK!
- /* write() test */
- write("out.d", "helloworld\negg"); // testing is OK!
- /* constractor test */
- TextFile tf = new TextFile("data.d"); // testing is OK!
- }
- }
2、读取二进制文件。
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- /**
- * to read the binary file
- *
- * @author erqing
- *
- */
- public class BinaryFile {
- /* the parametre is a file */
- public static byte[] read(File file) throws IOException {
- BufferedInputStream bf = new BufferedInputStream(new FileInputStream(
- file));
- try {
- byte[] data = new byte[bf.available()];
- bf.read(data);
- return data;
- } finally {
- bf.close();
- }
- }
- /* the param is the path of a file */
- public static byte[] read(String file) throws IOException {
- return read(new File(file).getAbsoluteFile());
- }
- }
Java IO详解(转)的更多相关文章
- Java IO 详解
Java IO 详解 初学java,一直搞不懂java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂.而且没有结合到java7 的最新技术,所以自己来整理一下,有错的话请指正, ...
- JAVA IO详解
[案例1]创建一个新文件 1 2 3 4 5 6 7 8 9 10 11 import java.io.*; class hello{ public static void main(Stri ...
- JAVA IO 详解2
Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 U ...
- Java IO详解(一)------字节输入输出流
File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...
- Java IO详解(二)------流的分类
一.根据流向分为输入流和输出流: 注意输入流和输出流是相对于程序而言的. 输出:把程序(内存)中的内容输出到磁盘.光盘等存储设备中 输入:读取外部数据(磁盘.光盘等存储设备的数据)到程序(内 ...
- Java IO详解(六)------序列化与反序列化(对象流)
File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...
- Java IO详解(五)------包装流
File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...
- Java IO详解(六)------随机访问文件流
File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...
- Java IO详解(四)------字符输入输出流
File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocea ...
随机推荐
- eclipse开发servlet应用,Tomcat无法访问jpg图片
今天遇到个奇怪的问题,我发现我放在tomcat的webapps文件夹项目下的jpg文件,浏览器无法访问: 以前没有遇到过这个问题,我知道肯定能访问的,因为以前做过相关应用,不知道问题出在哪. 后来我把 ...
- 2015 Multi-University Training Contest 5
#include <iostream> //1002 #include<set> #include<stdio.h> using namespace std; co ...
- ASP.NET生成压缩文件(rar打包)
首先引用ICSharpCode.SharpZipLib.dll,没有在这里下载:http://files.cnblogs.com/files/cang12138/ICSharpCode.SharpZi ...
- IDisposable接口详解
转载:http://www.cnblogs.com/davyli/archive/2010/09/13/1825042.html 正确实现 IDisposable .NET中用于释放对象资源的接口是I ...
- 关于android MTK相机L版本,切换屏幕比例后,分辨率随之改变,但重新进入相机后原有分辨率不再生效问题
BUG详细:比如4:3的时候是200W,切成全屏变400W,重新切回4:3为300W,退出相机后,重新进入又变成200W. 原因分析:这个版本的设计如此,当你点选屏幕比例的时候,程序设计是把这个比例值 ...
- Linux基本权限
首先需要我们了解的是,权限(rwx)对于文件和目录的作用是不一样的 . 权限对文件的作用 r : 读取文件内容(cat , more , head , tail) w: 编辑.新增.修改文件内容(vi ...
- Sqlite 错误码
#define SQLITE_OK 0 /* 成功 | Successful result */ /* 错误码开始 */ #define SQLITE_ERROR 1 /* SQL错误 或 丢失数据库 ...
- 苹果被拒的血泪史。。。(update 2015.11)
项目提交了N此了,也审核N次了,苹果的审核机制依旧那么不急不慢.昨天刚刚又被拒了.回忆下之前的,总结一下吧. 2015.04.28 昨天被拒非常亏,app的评级是17+,但是在app展示图里有一个比较 ...
- MapReduce中的排序
hadoop的计算模型就是map/reduce,每一个计算任务会被分割成很多互不依赖的map/reduce计算单元,将所有的计算单元执行完毕后整个计算任务就完成了.因为计算单元之间互不依 ...
- grails框架中在使用domain的save方法保存时保存不成功
1.如果报错,自行根据异常查找错误,这里不说明 2.如果为报错,我遇到的就是domain中的字段属性与数据库中为同步 (1)你的domain是新的,在增加新的字段属性时未使用update更新数据库,造 ...