Java IO.docx
- 文档编号:2241534
- 上传时间:2022-10-28
- 格式:DOCX
- 页数:24
- 大小:23.55KB
Java IO.docx
《Java IO.docx》由会员分享,可在线阅读,更多相关《Java IO.docx(24页珍藏版)》请在冰豆网上搜索。
JavaIO
笔记:
Java的IO性能调整
2010-06-12本站整理
摘要:
本文大多技术围绕调整磁盘文件I/O,但是有些内容也同样适合网络I/O和窗口输出。
第一部分技术讨论底层的I/O问题,然后讨论诸如压缩,格式化和串行化等高级I/O问题。
然而这个讨论没有包含应用设计问题,例如搜索算法和数据结构,也没有讨论系统级的问题,例如文件高速缓冲。
Java语言采取两种截然不同的磁盘文件结构。
一个是基于字节流,另一个是字符序列。
在Java语言中一个字符有两个字节表示,而不是像通常的语言如c语言那样是一个字节。
因此,从一个文件读取字符时需要进行转换。
这个不同在某些情况下是很重要的,就像下面的几个例子将要展示的那样。
低级I/O相关的问题:
∙缓冲
∙读写文本文件
∙格式化的代价
∙随机访问
高级I/O问题
∙压缩
∙高速缓冲
∙分解
∙串行化
∙获取文件信息
∙更多信息
加速I/O的基本规则
∙避免访问磁盘
∙避免访问底层的操作系统
∙避免方法调用
∙避免个别的处理字节和字符
很明显这些规则不能在所有的问题上避免,因为如果能够的话就没有实际的I/O被执行。
使用缓存减少读写次数开销
使用缓冲加速文件读取的示例:
对于一个1MB的输入文件,以秒为单位的执行时间是:
FileInputStream的read方法,每次读取一个字节,不用缓冲 6.9秒
BufferedInputStream的read方法使用BufferedInputStream 0.9秒
FileInputStream的read方法读取数据到直接缓冲 0.4秒
或者说在最慢的方法和最快的方法间是17比1的不同。
这个巨大的加速并不能证明你应该总是使用第三种方法,即自己做缓冲。
这可能是一个错误的倾向特别是在处理文件结束事件时没有仔细的实现。
在可读性上它也没有其它方法好。
但是记住时间花费在哪儿了以及在必要的时候如何矫正是很有用。
方法2或许是对于大多应用的"正确"方法.
方法2和3使用了缓冲技术,大块文件被从磁盘读取,然后每次访问一个字节或字符。
缓冲是一个基本而重要的加速I/O的技术,而且有几个类支持缓冲(BufferedInputStream用于字节,BufferedReader用于字符)。
缓冲区越大I/O越快吗?
典型的Java缓冲区长1024或者2048字节,一个更大的缓冲区有可能加速I/O但比重很小,大约5到10%。
方法1:
读方法
第一个方法简单的使用FileInputStream的read方法:
FileInputStream的read方法每次读取文件的下一个字节,触发了大量的底层运行时系统调用
优点:
编码简单,适用于小文件
缺点:
读写频繁,不适用于大文件
importjava.io.*;
publicclassintro1{
publicstaticvoidmain(Stringargs[]){
if(args.length!
=1){
System.err.println("missingfilename");
System.exit
(1);
}
try{
FileInputStreamfis=newFileInputStream(args[0]);//建立指向文件的读写流
intcnt=0;
intb;
while((b=fis.read())!
=-1){ // FileInputStream的read方法每次读取文件一个字节
if(b=='\n')
cnt++;
}
fis.close();
System.out.println(cnt);
}
catch(IOExceptione){
System.err.println(e);
}
}
}
方法2:
使用大缓冲区
第二种方法使用大缓冲区避免了上面的问题:
BufferedInputStream的read方法把文件的字节块读入缓冲区,然后每次读取一个字节,每次填充缓冲只需要访问一次底层存储接口
优点:
避免每个字节的底层读取,编码相对不复杂
缺点:
缓存占用了小量内存
importjava.io.*;
publicclassintro2{
publicstaticvoidmain(Stringargs[]){
if(args.length!
=1){
System.err.println("missingfilename");
System.exit
(1);
}
try{
FileInputStreamfis= newFileInputStream(args[0]);
BufferedInputStreambis=newBufferedInputStream(fis);//把文件读取流指向缓冲区
intcnt=0;
intb;
while((b=bis.read())!
=-1){ //BufferedInputStream的read方法把文件的字节块独
//入缓冲区BufferedInputStream,然后每次读取一个字节
if(b=='\n')
cnt++;
}
bis.close();
System.out.println(cnt);
}
catch(IOExceptione){
System.err.println(e);
}
}
}
方法3:
直接缓冲
FileInputStream的read方法直接读入字节块到直接缓冲buf,然后每次读取一个字节。
优点:
速度最快,
缺点:
编码稍微复杂,可读性差,占用了小量内存,
importjava.io.*;
publicclassintro3{
publicstaticvoidmain(Stringargs[]){
if(args.length!
=1){
System.err.println("missingfilename");
System.exit
(1);
}
try{
FileInputStreamfis=newFileInputStream(args[0]);
bytebuf[]=newbyte[2048];
intcnt=0;
intn;
while((n=fis.read(buf))!
=-1){// FileInputStream的read方法直接读入字节块到
//直接缓冲buf,然后每次读取一个字节
for(inti=0;i if(buf[i]=='\n') cnt++; } } fis.close(); System.out.println(cnt); } catch(IOExceptione){ System.err.println(e); } } } 方法4: 缓冲整个文件 缓冲的极端情况是事先决定整个文件的长度,然后读取整个文件。 优点: 把文件底层读取降到最少,一次, 缺点: 大文件会耗尽内存。 importjava.io.*; publicclassreadfile{ publicstaticvoidmain(Stringargs[]){ if(args.length! =1){ System.err.println("missingfilename"); System.exit (1); } try{ intlen=(int)(newFile(args[0]).length()); FileInputStreamfis=newFileInputStream(args[0]); bytebuf[]=newbyte[len]; //建立直接缓冲 fis.read(buf); //读取整个文件 fis.close(); intcnt=0; for(inti=0;i if(buf[i]=='\n') cnt++; } System.out.println(cnt); } catch(IOExceptione){ System.err.println(e); } } } 这个方法很方便,在这里文件被当作一个字节数组。 但是有一个明显得问题是有可能没有读取一个巨大的文件的足够的内存。 缓冲的另一个方面是向窗口终端的文本输出。 缺省情况下,System.out(一个PrintStream)是行缓冲的,这意味着在遇到一个新行符后输出缓冲区被提交。 格式化的代价 实际上向文件写数据只是输出代价的一部分。 另一个可观的代价是数据格式化。 考虑下面的字符输出程序 性能对比结果为: 这些程序产生同样的输出。 运行时间是: 格式化方法 示例语句 运行时间 简单的输出一个固定字符 System.out.print(s); 1.3秒 使用简单格式"+" Strings=字符+字符, System.out.print(s); 1.8秒 使用java.text包中的MessageFormat类的对象方法 Strings=fmt.format(values); System.out.print(s); 7.8秒 使用java.text包中的MessageFormat类的静态方法 7.8*1.3秒 最慢的和最快的大约是6比1。 如果格式没有预编译第三种方法将更慢,使用静态的方法代替: 第三个方法比前两种方法慢很多的事实并不意味着
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java IO