Java中有40多个与输入输出有关的类。假设不理清它们之间的关系。就不能灵活地运用它们。

假设从流的流向来分,可分为输入流和输出流,而输入流和输出流又都可分为字节流和字符流。因而可将Java中的I/O流下面图进行划分:

注意上图并不是继承关系,而仅仅是一个示意图。

Java中的其他与I/O流处理相关的类事实上都是从InputStream,Reader,OutputStream和Writer这4个基类继承而来。当中InputStream和OutputStream为字节流,Reader和Writer为字符流。

之所以这样划分。是由于计算机中全部的数据都是二进制的,而字节流可处理全部的二进制文件,但假设使用字节流来处理文本文件,也不是不能够,可是会更麻烦。所以通常有例如以下一个规则:假设进行输入/输出的内容是文本文件,则应该考虑使用字符流。假设进行输入/输出的内容是二进制内容(如图片、音频文件),则应该考虑使用字节流。

以下是从InputStream,Reader,OutputStream,Writer这4个基类出发,列出了经常使用的子类:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQmV0dGFyd2FuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

以下对各个类的特点及适用场合进行说明:

1.当中InputStreamReader和OutputStreamWriter是比較特殊的类。它们可将字节流转换为字符流,因而称为转换流。

如InputStreamReader reader=new InputStreamReader(System.in);

2.BufferedInputStream,BufferedOutputStream的使用方法尽管和FileInputStream,FileOutputStream的使用方法一样。可是效率却相差非常大,由于内存的效率比IO操作的效率要高得多。而BufferedInputStream,BufferedOutputStream会提前将文件里的内容读取(写入)到缓冲区。当读取(写入)时假设缓冲区存在就直接从缓冲区读,仅仅有缓冲区不存在对应内容时才会读取(写入)新的数据到缓冲区,并且一般会请求的数据要多。所以在读取(写入)文件,特别是较大的文件时,不要用最简单的FileInputStream和FileOutputStream,而要考虑使用BufferedInputStream,BufferedOutputStream.

3.ObjectInputStream,ObjectOutputStream则各自是将序列化的对象(即实现了Serializable接口的对象)读取出来/写入到文件里,显然,这事实上是利用反射的原理。

4.前面说过,Reader与InputStream的差别在于一个是字符输入流。一个是字节输入流。

FileReader与FileInputStream相应,BufferedReader与BufferedInputStream相应,所以在读取文本文件时最好使用BufferedReader而不要使用FileReader.

因为ByteArrayInputStream及PipedInputStream不经常使用,本文暂不讨论。

以下是一些代码实例:

首先是比較原始的读取文件的方法,即採用FileInputStream:

//这是读取字节流的实例
public class FileInputStreamSample { public static void main(String[]args) throws IOException
{
FileInputStream fis=new FileInputStream("d://error.dat");
byte[]buff=new byte[1024];
int hasRead=0;
while((hasRead=fis.read(buff))>0)
{
System.out.println(new String(buff,0,hasRead));
} fis.close(); }
}

然后是利用FileOutputStream进行文件的写入:

public class FileOutputStreamSample {

	public static void main(String[]args)
{
String fileName="d://error.dat";
//注意:不必提前新建,由于假设没有新建的话,它自己会新建一个。 String newFileName="d://error2.txt";
try
(FileInputStream fis=new FileInputStream(fileName);
FileOutputStream fos=new FileOutputStream(newFileName))
{
byte[]buff=new byte[32];
int hasRead=0;
while((hasRead=fis.read(buff))>0)
{
fos.write(buff,0,hasRead);
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}

比較高效的读取文件的方法。即採用BufferedInputStream:

public class BufferedInputStreamSample {

	public static void main(String[]args)
{
File file=new File("d://error.dat");
try
(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));)
{
byte[]buff=new byte[1024];
int hasRead=0;
while((hasRead=bis.read(buff))>0)
{
String content=new String(buff,0,hasRead);
System.out.println(content);
}
}
catch(IOException ex)
{
ex.printStackTrace();
} }
}

以下是比較高效的写入文件的方法。即採用BufferedOutputStream:

public class BufferedOutputStreamSample {

	public static void main(String[]args)
{
String content="I have a dream";
File file=new File("d://dream.dat"); byte[]buff=content.getBytes(); try
(BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));)
{
bos.write(buff);
//另外,bos另一个方法是bos.write(byte[],int arg1,int arg2);
}
catch(IOException ex)
{
ex.printStackTrace();
} }
}

以下是FileReader的使用方法,可是注意FileReader读取文本文件是比較低效的方法:

public class FileReaderSample {

	public static void main(String[]args)
{
try(
FileReader fr=new FileReader("d://error.dat")
)
{
char[]cbuff=new char[32];
int hasRead=0;
while((hasRead=fr.read(cbuff))>0)
{
System.out.println(new String(cbuff,0,hasRead));
} }
catch(IOException ex)
{
ex.printStackTrace();
}
}
}

类似地。FileWriter是比較低效的写入文本文件的方法:

public class FileWriterSample {

	public static void main(String[]args)
{
try
(FileWriter fw=new FileWriter("d://poem.txt"))
{
fw.write("I have a dream\n");
fw.write("One day on the red hills of Georgia\n");
fw.write("The sons of former slaves and the sons of former slave owner will be able to sit down together at the table.\n");
fw.write("My four little children will one day live in a nation where they will not be judged by the color of their skin but by the content of their character.\n"); }
catch(IOException ex)
{
ex.printStackTrace();
}
}
}

而BufferedReader是较高效的读取文本文件的方式。可是注意它的构造方法须要一个InputStreamReader,而InpuStreamReader又是包装FileInputStream而来,所以BufferedReader的用法例如以下:

public class BufferedReaderSample {

	public static void main(String[]args)
{
try
(
//假设是读取文件。则为InputStreamReader reader=new InputStreamReader(new InputStream("d://error.dat"));
//InputStreamReader reader=new InputStreamReader(new FileInputStream("d://error.dat"));
InputStreamReader reader=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(reader)
)
{
String buffer=null;
while((buffer=br.readLine())!=null)
{
System.out.println(buffer.toUpperCase());
} }
catch(IOException ex)
{
ex.printStackTrace();
}
}
}

显然。BufferedReader的优点是具有缓冲功能。它能够一次读取一行文本----以换行符为标志。上例是读取键盘输入后转换为大写并输出,当然,也能够读取文件后将各行转换为大写后输出。

BufferedWriter使用方法较简单,可是值得注意的是它要flush:

public class BufferedWriterSample {

	public static void main(String[]args)
{
try
(
//假设是写入到文件则为OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream("d://error.dat"));
OutputStreamWriter writer=new OutputStreamWriter(System.out);
BufferedWriter bw=new BufferedWriter(writer);
)
{
String content="Less is more\nLess is more is not a law\nLess is more is not always correct";
bw.write(content);
bw.flush();
}
catch(IOException ex)
{
ex.printStackTrace();
} }
}

以下是PrintStream,PrintWriter,BufferedWriter这3个类的对照:

首先是它们的共同点:都是处理流(包装流)而非节点流。因而能够更方便地使用,如PrintStream使用println(String)功能。BufferedWriter使用writer(String)功能;

PrintStream与PrintWriter,BufferedWriter的差别在于前者是处理字节流,而后两者是处理字符流;而BufferedWriter与PrintWriter相比。因为缓冲区的作用,它的效率要比PrintWriter要高。

以下是一个PrintStream的样例:

class Student
{
int id;
String name;
public Student()
{
id=0;
name="Jenny";
}
public String toString()
{
return "id="+id+" name="+name;
}
}
public class PrintStreamSample { public static void main(String[]args)
{
String fileName="d://poem.txt";
try
(PrintStream ps=new PrintStream(new FileOutputStream(fileName)))
{
//注意:这会把曾经的覆盖。要想不覆盖的话,就要使用ps.append的方法而不是println的方法。
ps.println("Less is more");
//直接使用println输出对象,这个在Socket编程时非常实用。
ps.println(new Student());
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}

以下是PrintWriter的一个样例:

public class PrintWriterSample {

	public static void main(String[]args)
{
try
(
PrintWriter writer=new PrintWriter(new OutputStreamWriter(System.out));
)
{
writer.println("Less is more is a important rule.");
writer.println(true);
} }
}

最后是ObjectInputStream及ObjectOutputStream,利用这两个类来读写序列化对象特别方便。例如以下所看到的:

public class ObjectOutputStreamSample {

	public static void main(String[]args)
{
Student stu1=new Student(1,"Jack","NewYork");
Student stu2=new Student(2,"Rose","California"); File file=new File("d://object.txt");
//由此可见,BufferedInputStream以及ObjectOutputStream事实上都是对FileOutputStream进行了包装。 try
(ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(file)))
{
oos.writeObject(stu1);
oos.writeObject(stu2); }
catch(IOException ex)
{
ex.printStackTrace();
} }
}
class Student implements Serializable{ private int id;
private String name;
private String address; public Student(int id,String name,String address)
{
this.id=id;
this.name=name;
this.address=address;
} @Override
public String toString()
{
StringBuilder sb=new StringBuilder();
sb.append("id:"+id);
sb.append(" ");
sb.append("name:"+name);
sb.append(" ");
sb.append("address:"+address);
return sb.toString();
} }
public class ObjectInputStreamSample {

	public static void main(String[]args)
{
File file=new File("d://object.txt");
try
(ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file)))
{
Student stu1=(Student)ois.readObject();
Student stu2=(Student)ois.readObject();
}
catch(Exception ex)
{
ex.printStackTrace();
} }
}

深入分析Java中的I/O类的特征及适用场合的更多相关文章

  1. 深入分析 Java 中的中文编码问题

    登录 (或注册) 中文 IBM 技术主题 软件下载 社区 技术讲座 打印本页面 用电子邮件发送本页面 新浪微博 人人网 腾讯微博 搜狐微博 网易微博 Digg Facebook Twitter Del ...

  2. [转]深入分析 Java 中的中文编码问题

    收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编 ...

  3. JAVA中封装JSONUtils工具类及使用

    在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...

  4. 深入分析 Java 中的中文编码问题(转)

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

  5. 深入分析 Java 中的中文编码问题 (文章来自网络)

    许令波,developerWorks 中国网站最佳作者,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,喜欢钻研开源框架的设计原理.有时间将学到的知识整理成文章,也喜欢记录 ...

  6. 深入分析 Java 中的中文编码问题--转

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

  7. Java中直接输出一个类的对象

    例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...

  8. 【JAVA编码专题】深入分析 Java 中的中文编码问题

    http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么 ...

  9. 深入分析 Java 中的中文编码问题(1)

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

随机推荐

  1. Boost.Asio c++ 网络编程翻译(16)

    TCP异步服务端 核心功能和同步服务端的功能类似,例如以下: class talk_to_client : public boost::enable_shared_from_this<talk_ ...

  2. QTP自带订票实现循环执行,參数化和将异常提示信息输出

    做这个样例主要是为了积累一些较基础的知识,以便日后可參考学习 这个样例是一个订票的C/Sclient程序 一.业务需求: 1.实现异常和正常数据登录窗体,系统对数据进行校验 2.登录成功后.进行订票业 ...

  3. poj 2683 Ohgas&#39; Fortune 利率计算

    水题. 代码: //poj 2683 //sep9 #include <iostream> using namespace std; int main() { int cases; sca ...

  4. Flex AsDoc 完整版

    Flex 生成AsDoc用的是SDK自带的asdoc.exe工具 生成AsDoc文档的方式有两种:ant或者FlashBuilder 外部配置工具 方法一:外部配置工具 新增一个外部配置工具.过程例如 ...

  5. 调用imagemagick做响应图片

    设计出图后经常需要改下尺寸放在别的项目上使用,每次都是设计手工处理,其实图片服务可以做更多事情,比如借助强大的im,可以通过url控制图片尺寸 var childProcess = require(' ...

  6. Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires

    Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server requires ...

  7. 《C++编程思想》第四章 初始化与清除(原书代码+习题+解答)

    相关代码: 1. #include <stdio.h> class tree { int height; public: tree(int initialHeight); ~tree(); ...

  8. ios-UI-汤姆猫德游戏实现

    // //  ViewController.m //  UI-猜拳游戏 // //  Created by jzq_mac on 15/7/15. //  Copyright (c) 2015年 jz ...

  9. 在阿里云的iis上安装php扩展

    具体参照http://jingyan.baidu.com/article/11c17a2c5ce349f447e39d6d.html

  10. C# web api 中过滤器的使用

    一.开篇 Fiter在Web API中经常会用到,主要用于记录日志,安全验证,全局错误处理等:Web API提供两种过滤器的基本类型:actionfilterattribute,exceptionfi ...