深入分析Java中的I/O类的特征及适用场合
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类的特征及适用场合的更多相关文章
- 深入分析 Java 中的中文编码问题
登录 (或注册) 中文 IBM 技术主题 软件下载 社区 技术讲座 打印本页面 用电子邮件发送本页面 新浪微博 人人网 腾讯微博 搜狐微博 网易微博 Digg Facebook Twitter Del ...
- [转]深入分析 Java 中的中文编码问题
收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编 ...
- JAVA中封装JSONUtils工具类及使用
在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...
- 深入分析 Java 中的中文编码问题(转)
几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...
- 深入分析 Java 中的中文编码问题 (文章来自网络)
许令波,developerWorks 中国网站最佳作者,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,喜欢钻研开源框架的设计原理.有时间将学到的知识整理成文章,也喜欢记录 ...
- 深入分析 Java 中的中文编码问题--转
几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...
- Java中直接输出一个类的对象
例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...
- 【JAVA编码专题】深入分析 Java 中的中文编码问题
http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么 ...
- 深入分析 Java 中的中文编码问题(1)
几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...
随机推荐
- 最小生成树基础 (Kruskal)
最小生成树 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- 光标属性CSS cursor 属性
CSS cursor 属性 CSS cursor属性,以前不知道,如果以后用到自己看的 <html> <body> <p>请把鼠标移动到单词上,可以看到鼠标指针发生 ...
- Spark RDD概念学习系列之如何创建Pair RDD
不多说,直接上干货! 创建Pair RDD Python语言 pairs = lines.map(lambda x: (x.split(], x)) scala语言 val pairs = line ...
- Centos7 minimal 系列之NAT联网(一)
一.安装 参考:http://m.blog.csdn.net/qq_24879495/article/details/77838512 二.解决不能联网问题 打开网络共享中心,设置虚拟网卡 编辑虚拟机 ...
- Cookie是存储在客户端上的一小段数据
背景 在HTTP协议的定义中,采用了一种机制来记录客户端和服务器端交互的信息,这种机制被称为cookie,cookie规范定义了服务器和客户端交互信息的格式.生存期.使用范围.安全性. 在JavaSc ...
- Java NIO(四)文件通道
文件通道 通道是访问I/O服务的导管,I/O可以分为广义的两大类:File I/O和Stream I/O.那么相应的,通道也有两种类型,它们是文件(File)通道和套接字(Socket)通道.文件通道 ...
- oracle错误ORA-00604 递归sql级别1出现错误 ora-00942 表或试图不存在 ORA-06512 在line 11
错误截图如下: 搜索了很多方法,但是都没有办法解决,不过最终还是找到了一个好的解决办法, 多谢那位仁兄的博客[http://blog.itpub.net/519536/viewspace-689469 ...
- js数组去重的四种方式
// 删除重复的 function only(arr){ for(var i=0;i<arr.length;i++){ for(var j = i+1;j<arr.length;j++){ ...
- HDU 2037 今年暑假不AC【贪心】
解题思路:即为给出一个总长度确定的区间,再输入不同的子区间,求在这个总区间里面包含的不相交的子区间最多有多少个. 可以由最特殊的情况来想,即给出的这些子区间现在都不相交,比如 ----- (1,3) ...
- 话说普通的TPlink ip地址是192.168.1.2 在LAN里有台电脑共享打印机 ip 是192.168.0.2 计算机名为j02 然后我把这台电脑加到DMZ里,让根路由器同一网段的可以访问 但添加打印机的时候 提示 计算机名重复 后来在需要添加打印机电脑的hosts文件里加了 192.168.1.2 j02 式了一样不行 话说,这个打印机该怎么添加
开启端口映射,从外网访问内网的文件共享: 已经在路由器里开了远端WEB管理设了端口,另外端口映射局域网里的一台电脑,比如WEB端口设的是8080,映射192.168.1.100到4877端口,现在我想 ...