快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

调整JavaTM 的I/O性能(二)(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);

              }

          }

      }

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


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




返回类别: 教程
上一教程: Java Socket编程(三)-1
下一教程: Java 面试中的陷阱

您可以阅读与"调整JavaTM 的I/O性能(二)(zt)"相关的教程:
· 调整JavaTM 的I/O性能(一)(zt)
· 调整JavaTM 的I/O性能(三)(zt)
· 调整JavaTM 的I/O性能(四)(zt)
· 调整 JAVATM I/O 性能
· 调整 Java I/O 性能
    微笑服务 优质保证 索取样品