转自:http://topic.csdn.net/u/20080310/10/bd73f657-f100-4e41-ad55-c8389251452d.html
java总是假定只有两种文件组织形式。
第一种,基于字节流(stream of bytes)
第二种,基于字符序列(character sequences)
java 中一个字符有两个字节。所以在从文件读字符时需要转换。
提高io性能的基本原则
1,尽量避免访问磁盘
2,尽量避免访问OS
3,尽量避免方法调用
4,尽量避免单独处理字节或字符
下面通过一个计算换行数的例子来说明这些原则是如何被应用的。
1,读
import java.io.*;
public class intro1 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileInputStream fis =
new FileInputStream(args[0]);
int cnt = 0;
int b;
while ((b = fis.read()) != -1) {
if (b == '\n')
cnt++;
}
fis.close();
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
这段代码中频繁调用了OS 函数,也就是FileInputStream.read
一个本地方法负责读取文件的下一个字节。
2,采用大缓存
import java.io.*;
public class intro2 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileInputStream fis =
new FileInputStream(args[0]);
BufferedInputStream bis =
new BufferedInputStream(fis);
int cnt = 0;
int b;
while ((b = bis.read()) != -1) {
if (b == '\n')
cnt++;
}
bis.close();
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
BufferedInputStream.read从缓存中读取字节。减少了底层api访问。
3,直接缓存
我们不使用BufferedInputStream 而是自己直接缓存。
这样可以减少方法调用。
import java.io.*;
public class intro3 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileInputStream fis =
new FileInputStream(args[0]);
byte buf[] = new byte[2048];
int cnt = 0;
int n;
while ((n = fis.read(buf)) != -1) {
for (int i = 0; i < n; i++) {
if (buf[i] == '\n')
cnt++;
}
}
fis.close();
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
对于1m的文件 执行时间分别是
intro1 6.9
intro2 0.9
intro3 0.4
最慢的和最快的时间比是 17 比 1
当然这并不是说我们总是要采用第三种方式。
其实第三种方式可能产生错误,特别是在处理end-of-file事件时(要仔细处理这类事件).
并且它可读性比较差.但是作为一个方法还是应该引起我们的注意.
第二种方式可能是最普通的方式.
【缓存】
第二种和第三种方式都用到了缓存.它确实是提高IO速度的基本手段。
这很容易让我们想起一个问题。是不是缓存越大IO越快。
JAVA 的缓存默认一般是1024 或 4048 比特。
更大的缓存可能加快IO但是也就是5% 10% 左右的小幅提升。
4,整个文件读取
import java.io.*;
public class readfile {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
int len = (int)(new File(args[0]).length());
FileInputStream fis =
new FileInputStream(args[0]);
byte buf[] = new byte[len];
fis.read(buf);
fis.close();
int cnt = 0;
for (int i = 0; i < len; i++) {
if (buf[i] == '\n')
cnt++;
}
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
这样很方便但也有很明显的不足,内存是不是比文件大。
另外一个缓存的关注点是向终端的输出。SYSTEM.OUT默认是行缓存,
也就是说缓存在遇到一个换行符的时候会将内容强行输出。
5,阻止行缓存
import java.io.*;
public class bufout {
public static void main(String args[]) {
FileOutputStream fdout =
new FileOutputStream(FileDescriptor.out);
BufferedOutputStream bos =
new BufferedOutputStream(fdout, 1024);
PrintStream ps =
new PrintStream(bos, false);
System.setOut(ps);
final int N = 100000;
for (int i = 1; i <= N; i++)
System.out.println(i);
ps.close();
}
}
这个程序输出1到100000到终端他比默认情况下快三倍。
【随机读写文本文件】
import java.io.*;
public class line1 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileInputStream fis =
new FileInputStream(args[0]);
BufferedInputStream bis =
new BufferedInputStream(fis);
DataInputStream dis =
new DataInputStream(bis);
int cnt = 0;
while (dis.readLine() != null)
cnt++;
dis.close();
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
这个程序用了古老的DataInputStream.readLine来读取字符。
新一点的方法会象下面这样
import java.io.*;
public class line2 {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("missing filename");
System.exit(1);
}
try {
FileReader fr = new FileReader(args[0]);
BufferedReader br = new BufferedReader(fr);
int cnt = 0;
while (br.readLine() != null)
cnt++;
br.close();
System.out.println(cnt);
}
catch (IOException e) {
System.err.println(e);
}
}
}
这个方法会快一些。比如6m 200,000行的文件读取第二种方式可以有20%的提升。
但即使没有提升也应该注意到一点。第一个方法会有警告,因为DataInputStream.readLine
这个方法没有正确变换字符,所以不要用它来处理文本文件。它可以处理ASCII的字节流。
来看下面这段程序
import java.io.*;
public class conv1 {
public static void main(String args[]) {
try {
FileOutputStream fos =
new FileOutputStream("out1");
PrintStream ps =
new PrintStream(fos);
ps.println("\uffff\u4321\u1234");
ps.close();
}
catch (IOException e) {
System.err.println(e);
}
}
}
显然他没有写我们能看懂的字符。
☆Reader/Writer IO类是基于字符的,它可以来解决这类问题。
OutputStreamWriter 是设置编码的地方。
import java.io.*;
public class conv2 {
public static void main(String args[]) {
try {
FileOutputStream fos =
new FileOutputStream("out2");
OutputStreamWriter osw =
new OutputStreamWriter(fos, "UTF8");
PrintWriter pw =
new PrintWriter(osw);
pw.println("\uffff\u4321\u1234");
pw.close();
}
catch (IOException e) {
System.err.println(e);
}
}
}
这段程序设置编码方式为UTF8。
分享到:
相关推荐
查看磁盘IO性能
关于IO性能的测试工具——Oracle Orion 在IT领域,尤其是数据库管理和系统性能优化方面,IO(输入/输出)性能的测试与分析至关重要。它直接影响着系统的响应速度、数据处理能力和用户体验。Oracle Orion作为一款...
虚拟化项目中的存储IO性能估算
linux下IO性能查找命令 集
在IT领域,尤其是在服务器管理中,对系统的性能监控至关重要,特别是磁盘I/O性能的监控。本报告聚焦于一个特定的场景,即在一台DELL R720服务器上运行Windows Server 2012时遇到的性能问题,通过监控和分析发现了...
存储基本IO性能测试指导书.doc
《WMI磁盘IO性能监控:深入理解与实践》 WMI(Windows Management Instrumentation,Windows管理工具)是微软提供的一种强大的系统管理框架,它允许开发者通过标准接口访问和操作Windows系统的各种管理信息,包括...
在SQL Server 2008中,内存管理和IO性能监控是数据库管理员进行系统优化和问题排查的关键环节。本文将深入探讨这两个方面的监控方法,帮助你更好地理解和管理SQL Server的资源利用。 一、内存管理 1. **内存架构**...
### Java IO性能优化 #### 4.1 基本IO操作 在Java开发中,`java.io`包是处理输入输出操作的核心组件。虽然它旨在简化开发人员的工作流程,但初学者常常会因为不了解其内部机制而做出降低IO性能的选择。通过深入...
生产系统主机IO性能分析是确保业务稳定运行的关键环节,尤其在面对高负载和大数据量时,磁盘IO性能成为衡量系统效能的重要指标。本文将深入探讨如何在Linux环境下监测和分析主机IO性能,涵盖dd命令的基本应用、...
在本主题“易语言磁盘IO性能监控”中,我们将深入探讨如何使用易语言来开发一个能够监控磁盘输入输出(I/O)性能的程序。 磁盘I/O性能是计算机系统中至关重要的部分,因为它直接影响到数据读写的速度,进而影响整个...
服务器IO性能评估作为服务器系统性能优化的基石,其重要性不言而喻。通过深入理解和掌握服务器磁盘IO的工作机制及性能评估方法,系统管理员和开发人员可以有效地识别系统瓶颈,从而采取合理的优化措施。本篇文章将...
"Linux 下使用 IOMETER 测试磁盘 IO 性能详解" Linux 作为一个开源的操作系统,具有高度的可扩展性和灵活性,广泛应用于服务器、数据中心、云计算等领域。在 Linux 下测试磁盘 IO 性能非常重要,因为磁盘 IO 性能...
在Linux环境中,对磁盘IO性能进行测试是评估系统整体性能的重要环节,因为磁盘的读写速度直接影响到数据存取效率。IOMETER是一款强大的性能基准测试工具,它能够帮助用户测量磁盘、网络存储设备以及服务器的性能。...
### SUSE系统与SUSERT系统IO性能评测研究 #### 一、国内外研究现状与背景 随着信息技术的快速发展,Linux操作系统因其开源性、稳定性和安全性等特点,在服务器领域得到了广泛的应用。其中,SUSE Linux Enterprise ...
### 利用缓冲区提高Java应用程序的IO性能 #### 摘要与背景介绍 Java作为一门具有跨平台特性的编程语言,在多个领域都获得了广泛的应用。随着Java应用的不断扩展,其性能问题逐渐成为人们关注的重点,尤其是输入...
在“易语言WMI磁盘IO性能监控”项目中,我们主要探讨的是如何利用易语言来实现对计算机磁盘输入/输出(I/O)性能的实时监控。 WMI(Windows Management Instrumentation)是微软提供的一个系统管理框架,它允许程序...
易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar 易语言WMI磁盘IO性能监控易语言源码.rar ...
本文将分析Java NIO与Java IO在性能上的对比,并尝试找出性能差异的原因,以及探讨哪种编程模型更适合高并发的应用场景。 Java IO模型是一种阻塞型I/O模型,在数据的读写过程中,如果线程在等待数据,将会一直被挂...
**Iometer:全面解析磁盘与网络IO性能测试工具** Iometer是一款由Intel公司研发的高性能、跨平台的输入/输出(I/O)基准测试工具,主要用于评估系统在处理磁盘和网络I/O请求时的性能。它适用于各种操作系统,包括...