繁体中文
设为首页
加入收藏
当前位置:JSP技术首页 >> 资料/其它 >> 调整JavaTM 的I/O性能(二)(zt)

调整JavaTM 的I/O性能(二)(zt)

2005-04-15 08:00:00  作者:  来源:互联网  浏览次数:0  文字大小:【】【】【
简介:格式化开销 实际上,将数据写入文件只是输出开销的一部分。另外一个巨大的开销是数据的格式 化。考虑下面的三个例 子,要求其输出如下的行: The square of 5 is 25 方法 1 第一种方法是简单地输出一个固定串,以...
关键字:性能 调整 JavaTM zt

格式化开销

实际上,将数据写入文件只是输出开销的一部分。另外一个巨大的开销是数据的格式 化。考虑下面的三个例 子,要求其输出如下的行:

The square of 5 is 25

方法 1

第一种方法是简单地输出一个固定串,以得到内部I/O开销的概念:

public class format1 {

public static void main(String args[]) {

final int COUNT = 25000;

for (int i = 1; i <= COUNT; i++) {

String s = "The square of 5 is 25\n";

System.out.print(s);

}

}

}

方法 2

第二种方法采用带"+"的简单格式化:

public class format2 {

public static void main(String args[]) {

int n = 5;

final int COUNT = 25000;

for (int i = 1; i <= COUNT; i++) {

String s = "The square of " + n + " is " + n * n + "\n";

System.out.print(s);

}

}

}

方法 3

第三种方法使用了java.text包中的类MessageFormat:

import java.text.*;

public class format3 {

public static void main(String args[]) {

MessageFormat fmt =

new MessageFormat("The square of {0} is {1}\n");

Object values[] = new Object[2];

int n = 5;

values[0] = new Integer(n);

values[1] = new Integer(n * n);

final int COUNT = 25000;

for (int i = 1; i <= COUNT; i++) {

String s = fmt.format(values);

System.out.print(s);

}

}

}

这些程序产生相同的输出,运行时间为:

format1 1.3

format2 1.8

format3 7.8

最快和最慢之间的差距为6比1。如果该格式没有进行预编译,并且采用了便利的静态方法,第三个程序将更 慢。

方法 4

使用MessageFormat.format(String, Object[])方法如下:

import java.text.*;

public class format4 {

public static void main(String args[]) {

String fmt = "The square of {0} is {1}\n";

Object values[] = new Object[2];

int n = 5;

values[0] = new Integer(n);

values[1] = new Integer(n * n);

final int COUNT = 25000;

for (int i = 1; i <= COUNT; i++) {

String s = MessageFormat.format(fmt, values);

System.out.print(s);

}

}

}

这比前一个例子花费的时间还要长1/3。

方法3比1、2慢一点,并不意味不应该采用它。但是,应该明白在时间上的代价。

在国际化语言环境中,消息的格式是非常重要的,涉及到这个问题的应用程序通常从一个资源文件中读取该 格式,然后使用它。

随机存储

RandomAccessFile是用于对文件进行随机I/O存储(在字节层次上)的一个Java类。该类提供了一个与C/C++中 相似的搜索方法,以将文件指针移动到任意位置,然后就可以对从那里开始的字节进行读或写了。 该搜索方法访问底层的运行系统,正因为如此,开销可能非常昂贵。一个稍微廉价的替代方法是,在 RandomAccessFile顶部设置自己的缓冲,并且实现对字节的直接读取方法。用于读取的参数是所需字节的字节 偏移量。下面的例子显示了这是如何进行的:

import java.io.*;

public class ReadRandom {

private static final int DEFAULT_BUFSIZE = 4096;

private RandomAccessFile raf;

private byte inbuf[];

private long startpos = -1;

private long endpos = -1;

private int bufsize;

public ReadRandom(String name)

throws FileNotFoundException {

this(name, DEFAULT_BUFSIZE);

}

public ReadRandom(String name, int b)

throws FileNotFoundException {

raf = new RandomAccessFile(name, "r");

bufsize = b;

inbuf = new byte[bufsize];

}

public int read(long pos) {

if (pos < startpos || pos > endpos) {

long blockstart = (pos / bufsize) * bufsize;

int n;

try {

raf.seek(blockstart);

n = raf.read(inbuf);

}

catch (IOException e) {

return -1;

}

startpos = blockstart;

endpos = blockstart + n - 1;

if (pos < startpos || pos > endpos)

return -1;

}

return inbuf[(int)(pos - startpos)] & 0xffff;

}

public void close() throws IOException {

raf.close();

}

public static void main(String args[]) {

if (args.length != 1) {

System.err.println("missing filename");

System.exit(1);

}

try {

ReadRandom rr = new ReadRandom(args[0]);

long pos = 0;

int c;

byte buf[] = new byte[1];

while ((c = rr.read(pos)) != -1) {

pos++;

buf[0] = (byte)c;

System.out.write(buf, 0, 1);

}

rr.close();

}

catch (IOException e) {

System.err.println(e);

}

}

}

本驱动器程序简单地顺序读取字节,并且输出。

如果拥有存储的局部性(在文件中相邻位置的字节可以被同时读取),那么这项技术很有帮助。例如,如果 在已排序的文件中实现二叉树搜索算法,此方法可能很有用。如果在一个大文件中的任意位置进行随机存 储,其价值较小。

责任编辑:admin
相关文章