|            
压缩 
 
  Java提供了对字节流进行压缩和解压缩的类。它们可以在java.util.zip包中被找到,同时也作为Jar文件的基 础(Jar文件是具有一个清单的Zip文件)。 
 
  以下的程序采用一个单一的输入文件,并且生成一个压缩了的Zip输出文件,该程序带有一个表示输入文件的 入口项。 
 
  import java.io.*; 
  import java.util.zip.*; 
 
 
  public class compress { 
  public static void doit(String filein, String fileout) { 
  FileInputStream fis = null; 
  FileOutputStream fos = null; 
  try { 
  fis = new FileInputStream(filein); 
  fos = new FileOutputStream(fileout); 
  ZipOutputStream zos = new ZipOutputStream(fos); 
  ZipEntry ze = new ZipEntry(filein); 
  zos.putNextEntry(ze); 
  final int BUFSIZ = 4096; 
  byte inbuf[] = new byte[BUFSIZ]; 
  int n; 
  while ((n = fis.read(inbuf)) != -1) 
  zos.write(inbuf, 0, n); 
  fis.close(); 
  fis = null; 
  zos.close(); 
  fos = null; 
  } 
  catch (IOException e) { 
  System.err.println(e); 
  } 
  finally { 
  try { 
  if (fis != null) 
  fis.close(); 
  if (fos != null) 
  fos.close(); 
  } 
  catch (IOException e) { 
  } 
  } 
  } 
 
 
  public static void main(String args[]) { 
  if (args.length != 2) { 
  System.err.println("missing filenames"); 
  System.exit(1); 
  } 
  if (args[0].equals(args[1])) { 
  System.err.println("filenames are identical"); 
  System.exit(1); 
  } 
  doit(args[0], args[1]); 
  } 
  }
  下一个程序正好相反,采用假定只有一个入口项的Zip输入文件,并且将该项解压到指定的输出文件: 
 
  import java.io.*; 
  import java.util.zip.*; 
 
 
  public class uncompress { 
  public static void doit(String filein, String fileout) { 
  FileInputStream fis = null; 
  FileOutputStream fos = null; 
  try { 
  fis = new FileInputStream(filein); 
  fos = new FileOutputStream(fileout); 
  ZipInputStream zis = new ZipInputStream(fis); 
  ZipEntry ze = zis.getNextEntry(); 
  final int BUFSIZ = 4096; 
  byte inbuf[] = new byte[BUFSIZ]; 
  int n; 
  while ((n = zis.read(inbuf, 0, BUFSIZ)) != -1) 
  fos.write(inbuf, 0, n); 
  zis.close(); 
  fis = null; 
  fos.close(); 
  fos = null; 
  } 
  catch (IOException e) { 
  System.err.println(e); 
  } 
  finally { 
  try { 
  if (fis != null) 
  fis.close(); 
  if (fos != null) 
  fos.close(); 
  } 
  catch (IOException e) { 
  } 
  } 
  } 
 
 
  public static void main(String args[]) { 
  if (args.length != 2) { 
  System.err.println("missing filenames"); 
  System.exit(1); 
  } 
  if (args[0].equals(args[1])) { 
  System.err.println("filenames are identical"); 
  System.exit(1); 
  } 
  doit(args[0], args[1]); 
  } 
  }
  压缩是有助还是损害I/O性能很大程度上依赖于本地硬件设置;尤其是处理器和磁盘驱动器的相对速度。采用 Zip技术进行压缩,典型地将数据量减少50%,但是有一些压缩和解压的时间开销。在带IDE磁盘驱动器的 300-MHz Pentium PC上,对一个大的压缩文本文件(5-10MB)的实验表明,从磁盘读取压缩文件比非压缩文件 快将近1/3。 
 
  充分展现压缩优越性的一个例子是在写入象软盘这样的低速介质。使用高速处理器 (300 MHz Pentium)和低 速软盘(PC上常用的软盘驱动器)进行的测试显示,压缩一个大文本文件,然后写入软盘,比直接将文件拷 贝到软盘快50%。 
 
  高速缓存 
 
  关于硬件的高速缓存的详细讨论超出了本文的范围。但是,有时软件高速缓存 能够加速I/O。考虑这样一个 例子,需要以随机的方式读取文本文件的某些行。完成的方法之一是读入所有的行,并且把它们存储在 ArrayList(一个与Vector相似的collection类)中: 
 
  import java.io.*; 
  import java.util.ArrayList; 
 
 
  public class LineCache { 
  private ArrayList list = new ArrayList(); 
 
 
  public LineCache(String fn) throws IOException { 
  FileReader fr = new FileReader(fn); 
  BufferedReader br = new BufferedReader(fr); 
  String ln; 
  while ((ln = br.readLine()) != null) 
  list.add(ln); 
  br.close(); 
  } 
 
 
  public String getLine(int n) { 
  if (n < 0) 
  throw new IllegalArgumentException(); 
 
 
  return (n < list.size() ? 
  (String)list.get(n) : null); 
  } 
 
 
  public static void main(String args[]) { 
  if (args.length != 1) { 
  System.err.println("missing filename"); 
  System.exit(1); 
  } 
  try { 
  LineCache lc = new LineCache(args[0]); 
  int i = 0; 
  String ln; 
  while ((ln = lc.getLine(i++)) != null) 
  System.out.println(ln); 
  } 
  catch (IOException e) { 
  System.err.println(e); 
  } 
  } 
  }
  getLine方法被用来检索任意的一行。这项技术非常有用,但对于大文件而言,显然需要使用了大量的内存, 因此具有局限性。一个替代方法是仅仅记住最近被请求的100行,必要时从磁盘上读取其他行。在存在行的存 储局部性这种情况下,这个方案运行良好,但是需要真正的随机存储时就没有这么好了。 
 
  标志化(Tokenization) 
 
  标志化(Tokenization)指将字节或者字符序列拆散成象词一样的逻辑块的过程。Java提供了StreamTokenizer 类,可以进行如下的操作: 
 
  import java.io.*; 
 
 
  public class token1 { 
  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); 
  StreamTokenizer st = new StreamTokenizer(br); 
  st.resetSyntax(); 
  st.wordChars('a', 'z'); 
  int tok; 
  while ((tok = st.nextToken()) != 
  StreamTokenizer.TT_EOF) { 
  if (tok == StreamTokenizer.TT_WORD) 
  ; // st.sval has token 
  } 
  br.close(); 
  } 
  catch (IOException e) { 
  System.err.println(e); 
  } 
  } 
  }
  本例根据小写字母(字母a-z)进行标记。如果由您自己实现了其等效程序,可能看上去象这样: 
 
  import java.io.*; 
 
 
  public class token2 { 
  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 maxlen = 256; 
  int currlen = 0; 
  char wordbuf[] = new char[maxlen]; 
  int c; 
  do { 
  c = br.read(); 
  if (c >= 'a' && c <= 'z') { 
  if (currlen == maxlen) { 
  maxlen *= 1.5; 
  char xbuf[] = 
  new char[maxlen]; 
  System.arraycopy( wordbuf, 0, 
  xbuf, 0, currlen); 
  wordbuf = xbuf; 
  } 
  wordbuf[currlen++] = (char)c; 
  } 
  else 
  if (currlen > 0) { 
  String s = new String(wordbuf, 0, 
  currlen); 
  // do something with s 
  currlen = 0; 
  } 
  } while (c != -1); 
  br.close(); 
  } 
  catch (IOException e) { 
  System.err.println(e); 
  } 
  } 
  }
 
   
 |