相信好多人都对java的io类感到抓狂,一个简单的输入输出都要创建n多个对象,完全搞不懂为什么要一层套一层。
如果你也有上面的困惑,那么不妨和我一起究一究为什么Java IO长这样。
我猜Java IO的创建过程是这样的:
先参考一下其它已有编程语言都是怎么创建IO类的。IO输入/输出源各种各样,有键盘输入,有文件输入,有网络输入,有内存输入等等。为了屏蔽这些不同,编程语言都引入了“流"的概念,说白了所有这些IO操作就是字节流流来流去。
这些流又可以分为两大类,输入流和输出流。
于是乎Java 1.0 便也照猫画虎提供了两大类IO类库, InputStream, OutputStream.
有了这两个基类以后,创建者认为基本IO问题就搞定了,如果你需要输入那你就继承InputStream, 如果你需要输出那么你就继承OutputStream.
Java 提供了几种常用输入输出的实现。我们可以直接使用
ByteArrayInputStream 用于从内存的缓冲区读取数据, 如一个线程将数据写入某个缓冲区,另一个线程可以用ByteArrayInputStream读取该缓冲区的数据;
ByteArrayOutputStream, 将内容写入内存的某缓冲区;
public static void main(String[] args) throws IOException{
ByteArrayInputStream input = new ByteArrayInputStream("memory input test".getBytes());
ByteArrayOutputStream output = new ByteArrayOutputStream();
int data = 0;
while((data = input.read()) != -1){
output.write(data);
}
System.out.print(output.toString());
input.close();
output.close();
}
FileInputStream, 用于从文件中读取数据;
FileOutputStream, 用于将内容写入文件。
public static void readFile(String inFile, String outFile) throws IOException{
try {
byte[] data = new byte[1];
FileOutputStream output = new FileOutputStream(outFile);
FileInputStream input = new FileInputStream(new File(inFile));
try {
while(input.available() > 0){
input.read(data);
output.write(data);
}
} finally{
input.close();
output.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
这些实现都是基于InputStream/OutputStream 的,都是以字节为单位读取/写入数据。
读起来确实难用,byte[]设大了吧,如果数据没呢么多久会写好多null,设小了吧效率不高。
在使用过程中人们就发现很多问题,如文件读取很慢,因为磁盘读取本来就很耗时,以字节为单位和磁盘交互,每次只读取一个字节效率自然太慢了;
如果只是单纯的都一个文件然后写到另一个文件,这个方法还算能用。
但是当要解析里面的数据时就有问题了,不同的数据类型所占用的存储空间也不同,如在某些机子上int占4个byte, double占8个byte, 而在另一些机器上可能所占空间又不同,当我需要读取一个int时我是读取4个byte呢,还是5个byte呢?
此时想解决这个问题有两种方法,一种是将前面的推倒重来,放弃之前的类再写两个新的替代它们;另一个方法就是使用装饰折模式在前面基础上进行修补。
Java选择了后者,它可以简单的装饰一下原有的类,然后和原有类提供完全一样的接口,只是对它的功能稍加装饰,满足现在的需求。
于是针对上面两个问题就有了BufferedInputStream, DataInputStream, BufferedOutputStream, DataOutputStream 来对FileInputStream/FileOutputStream进行装饰。
BufferedInputStream/BufferedOutputStream 就可以使你在读写文件的时候一次读写一批数据,而不是一个byte一个byte读取,大大加强磁盘读写效率;
public static void BufferTest(String inputName, String outputName) throws IOException{
try {
byte[] data = new byte[1];
BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File(inputName)));
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(outputName));
try {
while(input.available() > 0){
input.read(data);
output.write(data);
}
} finally{
input.close();
output.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
虽然看上去操作和FileInputStream/FileOutputStream没差,但BufferedInputStream/BufferedOutputStream内部其实并不是一次读一个byte,而是每次读得时候预取好多,下次再读可直接从内存得到,大大提升效率。
DataInputStream/DataOutputStream 则可以让你直接按照字符来读写,而不是基于字节,这样我们就不用关心这个整数在这台机子上到底占用几个字节了,InputStream.readInt()直接读取到一个int.
public static void dataInputOutputTest(String fileName) throws FileNotFoundException{
DataInputStream input = null;
DataOutputStream output = new DataOutputStream(new FileOutputStream(fileName));
int a = 10;
float b = 12;
String c = "test";
try {
output.writeInt(a);
output.writeFloat(b);
output.writeUTF(c);
output.flush();
output.close();
input = new DataInputStream(new FileInputStream(fileName));
System.out.println(input.readInt());
System.out.println(input.readFloat());
System.out.println(input.readUTF());
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
貌似所有问题都解决了,文件copy用字节流,读取字符用DataInputStream, DataOutputStream。
但是DataOutputStream的问题是它写的文件不可读;而且读得顺序必须和写的顺序一模一样,比较适合于固定格式的输入,输出。而我们90%的情况下其实都是在读取String。
Java1.1 发现了这些问题,于是乎对IO又有了一个革命性的改写,我们下回分析
分享到:
相关推荐
作者力求做到知识的综合传播,而不是仅仅只针对Java虚拟机调优进行讲解,另外力求每一章节都有实际的案例支撑。具体包括:性能优化策略、程序编写及硬件服务器的基础知识、Java API优化建议、算法类程序的优化建议、...
大话Java:从零基础到数据库、Web开发以漫画的形式,由浅入深、循序渐进地介绍Java编程的常用技术和方法,内容涵盖了Java基本语法结构、面向对象特征、集合框架体系、异常处理、GUI编程、MySQL数据库、JDBC数据库...
《大话java性能优化》是周明耀先生的一本深入探讨Java性能调优的专业书籍,其主要内容涵盖了Java程序设计中的各种性能优化策略和技术。这本书旨在帮助开发者理解和掌握如何提升Java应用的运行效率,减少资源消耗,...
大话java性能优化,大家可以搜一下这本书。这个是完美中文版,建议下载
但根据标题《大话JAVA性能优化》和描述“虽然有些地方可能过时,但是还是可以一读”以及标签“java 优化”,可以推断出书籍内容可能围绕Java编程语言的性能优化相关知识。基于这些信息,我们可以构建关于Java性能...
大话java性能优化,pdf版!
《Java版大话西游源码》是一款基于Java编程语言开发的角色扮演游戏(RPG)教程,对于初学者和想要深入理解游戏开发的程序员来说,它提供了丰富的学习资源。这款教程涵盖了多线程技术和自动寻路算法等核心概念,是...
作者 力求 做到 知识 的 综合 传播, 而 不是 仅仅 只 针对 Java 虚拟 机 调 优 进行 讲解, 另外 力求 每一 章节 都有 实际 的 案例 支撑。 具体 包括: 性能 优化 策略、 程序 编写 及 硬件 服务器 的 基础 知识...
大话JAVA性能优化-高清-2016年4月,分享给所有需要的人!
作者力求做到知识的综合传播,而不是仅仅只针对Java虚拟机调优进行讲解,另外力求每一章节都有实际的案例支撑。具体包括:性能优化策略、程序编写及硬件服务器的基础知识、Java API优化建议、算法类程序的优化建议、...
Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向...
设计模式参考《大话设计模式》 工厂简单模式 创造型模式 工厂方法模式 抽象工厂模式 原型模式 建造者模式 单例模式 结构型模式 队列模式 桥接模式 组合模式 装饰模式 外观模式 享元模式 代理模式 行为模式(类行为...
(JAVA)大话类、方法、参数、对象、属性以及面向对象的开发模式.pdf
本人十余年JAVA从业经验,精通JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA职业规划、技术提升的可与我联系,交个朋友~ 本人十余年JAVA从业经验,精通JAVA高可用、分布式、高并发系统架构设计。有志于做...
十四万字总结,PDF包含了十四个大模块:Java基础知识,数据结构,算法,Java集合框架,Java8新特性,操作系统,网络原理,Java多线程及并发编程,Java的IO模型及网络编程,JVM,Mysql,JavaWeb和一个仿Tomcat实现的...
8. 包名命名:包名应该全部使用小写,并且用点分隔符来分隔,每个部分仅包含一个自然语义的英语单词。包名的命名也应使用单数形式,除非类名具有复数含义。 9. 缩写命名:避免使用不规范的缩写,因为这会降低代码的...
大话西游模拟仿制后端