亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

【轉(zhuǎn)載】java IO優(yōu)化

abson / 1393人閱讀

摘要:摘要本文大多技術(shù)圍繞調(diào)整磁盤(pán)文件但是有些內(nèi)容也同樣適合網(wǎng)絡(luò)和窗口輸出。語(yǔ)言采取兩種截然不同的磁盤(pán)文件結(jié)構(gòu)。一個(gè)是基于字節(jié)流,另一個(gè)是字符序列。但是在有些情況下軟件高速緩存能被用于加速。串行化串行化以標(biāo)準(zhǔn)格式將任意的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為字節(jié)流。

摘要

本文大多技術(shù)圍繞調(diào)整磁盤(pán)文件 I/O,但是有些內(nèi)容也同樣適合網(wǎng)絡(luò) I/O 和窗口輸出。
第一部分技術(shù)討論底層的I/O問(wèn)題,然后討論諸如壓縮,格式化和串行化等高級(jí)I/O問(wèn)題。然而這個(gè)討論沒(méi)有包含應(yīng)用設(shè)計(jì)問(wèn)題,例如搜索算法和數(shù)據(jù)結(jié)構(gòu),也沒(méi)有討論系統(tǒng)級(jí)的問(wèn)題,例如文件高速緩沖。
Java語(yǔ)言采取兩種截然不同的磁盤(pán)文件結(jié)構(gòu)。一個(gè)是基于字節(jié)流,另一個(gè)是字符序列。在Java 語(yǔ)言中一個(gè)字符由兩個(gè)字節(jié)表示,而不是像通常的語(yǔ)言如c語(yǔ)言那樣是一個(gè)字節(jié)。因此,從一個(gè)文件讀取字符時(shí)需要進(jìn)行轉(zhuǎn)換。這個(gè)不同在某些情況下是很重要的, 就像下面的幾個(gè)例子將要展示的那樣。

低級(jí)I/O相關(guān)的問(wèn)題:

緩沖

讀寫(xiě)文本文件

格式化的代價(jià)

隨機(jī)訪問(wèn)
高級(jí)I/O問(wèn)題

壓縮

高速緩沖

分解

串行化

獲取文件信息
更多信息

加速I(mǎi)/O的基本規(guī)則

避免訪問(wèn)磁盤(pán)

避免訪問(wèn)底層的操作系統(tǒng)

避免方法調(diào)用

避免個(gè)別的處理字節(jié)和字符
很明顯這些規(guī)則不能在所有的問(wèn)題上避免,因?yàn)槿绻軌虻脑捑蜎](méi)有實(shí)際的I/O被執(zhí)行。

使用緩存減少讀寫(xiě)次數(shù)開(kāi)銷(xiāo)

使用緩沖加速文件讀取的示例:

 對(duì)于一個(gè)1 MB的輸入文件,以秒為單位的執(zhí)行時(shí)間是:
FileInputStream的read方法,每次讀取一個(gè)字節(jié),不用緩沖 6.9秒
BufferedInputStream的read方法使用BufferedInputStream 0.9秒
FileInputStream的read方法讀取數(shù)據(jù)到直接緩沖 0.4秒

或者說(shuō)在最慢的方法和最快的方法間是17比1的不同。

這個(gè)巨大的加速并不能證明你應(yīng)該總是使用第三種方法,即自己做緩沖。這可能是一個(gè)錯(cuò)誤的傾向特別是在處理文件結(jié)束事件時(shí)沒(méi)有仔細(xì)的實(shí)現(xiàn)。在可讀性上它也沒(méi)有其它方法好。但是記住時(shí)間花費(fèi)在哪兒了以及在必要的時(shí)候如何矯正是很有用。方法2 或許是對(duì)于大多應(yīng)用的 "正確" 方法.
方法 2 和 3 使用了緩沖技術(shù), 大塊文件被從磁盤(pán)讀取,然后每次訪問(wèn)一個(gè)字節(jié)或字符。緩沖是一個(gè)基本而重要的加速I(mǎi)/O 的技術(shù),而且有幾個(gè)類(lèi)支持緩沖(BufferedInputStream 用于字節(jié), BufferedReader 用于字符)。
緩沖區(qū)越大I/O越快嗎?典型的Java緩沖區(qū)長(zhǎng)1024 或者 2048 字節(jié),一個(gè)更大的緩沖區(qū)有可能加速 I/O但比重很小,大約5 到10%。

方法1: 讀方法

第一個(gè)方法簡(jiǎn)單的使用FileInputStream的read方法:

FileInputStream的read方法每次讀取文件的下一個(gè)字節(jié),觸發(fā)了大量的底層運(yùn)行時(shí)系統(tǒng)調(diào)用
優(yōu)點(diǎn):編碼簡(jiǎn)單,適用于小文件
缺點(diǎn):讀寫(xiě)頻繁,不適用于大文件

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]); // 建立指向文件的讀寫(xiě)流
       int cnt = 0;
       int b;
       while ((b = fis.read()) != -1 ) {  // FileInputStream 的read方法每次 讀取文件一個(gè)字節(jié)
         if (b == "
")
           cnt++;
       }
       fis.close();
       System.out.println(cnt);
     }
     catch (IOException e) {
       System.err.println(e);
     }
   }
 }
方法 2: 使用大緩沖區(qū)

第二種方法使用大緩沖區(qū)避免了上面的問(wèn)題:

BufferedInputStream的read方法 把文件的字節(jié)塊讀入緩沖區(qū),然后每次讀取一個(gè)字節(jié),每次填充緩沖只需要訪問(wèn)一次底層存儲(chǔ)接口
優(yōu)點(diǎn):避免每個(gè)字節(jié)的底層讀取,編碼相對(duì)不復(fù)雜
缺點(diǎn):緩存占用了小量?jī)?nèi)存

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); // 把文件讀取流指向緩沖區(qū)
      int cnt = 0;
      int b;
      while ((b = bis.read()) != -1 ) {   //BufferedInputStream 的read方法 把文件的字節(jié)塊獨(dú)     
                                  //入緩沖區(qū)BufferedInputStream,然后每次讀取一個(gè)字節(jié)
        if (b == "
")
          cnt++;
        }
      bis.close();
      System.out.println(cnt);
    }
    catch (IOException e) {
      System.err.println(e);
    }
  }
 }
 方法 3: 直接緩沖

FileInputStream的read方法直接讀入字節(jié)塊到直接緩沖buf,然后每次讀取一個(gè)字節(jié)。
優(yōu)點(diǎn):速度最快,
缺點(diǎn):編碼稍微復(fù)雜,可讀性差,占用了小量?jī)?nèi)存,

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 ) { // FileInputStream 的read方法直接讀入字節(jié)塊到
                                     //直接緩沖buf,然后每次讀取一個(gè)字節(jié)
          for (int i = 0; i < n; i++) {
            if (buf[i] == "
")
              cnt++;
          }
        }
        fis.close();
        System.out.println(cnt);
      }
      catch (IOException e) {
        System.err.println(e);
      }
    }
  }
方法4: 緩沖整個(gè)文件

緩沖的極端情況是事先決定整個(gè)文件的長(zhǎng)度,然后讀取整個(gè)文件。
優(yōu)點(diǎn):把文件底層讀取降到最少,一次,
缺點(diǎn):大文件會(huì)耗盡內(nèi)存。

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);                             // 讀取整個(gè)文件
        fis.close();
        int cnt = 0;
        for (int i = 0; i < len; i++) {
          if (buf[i] == "
")
            cnt++;
        }
        System.out.println(cnt);
      }
      catch (IOException e) {
        System.err.println(e);
      }
    }
  }

這個(gè)方法很方便,在這里文件被當(dāng)作一個(gè)字節(jié)數(shù)組。但是有一個(gè)明顯得問(wèn)題是有可能沒(méi)有讀取一個(gè)巨大的文件的足夠的內(nèi)存。
緩沖的另一個(gè)方面是向窗口終端的文本輸出。缺省情況下, System.out ( 一個(gè)PrintStream) 是行緩沖的,這意味著在遇到一個(gè)新行符后輸出緩沖區(qū)被提交。

格式化的代價(jià)

實(shí)際上向文件寫(xiě)數(shù)據(jù)只是輸出代價(jià)的一部分。另一個(gè)可觀的代價(jià)是數(shù)據(jù)格式化。
考慮下面的字符輸出程序
性能對(duì)比結(jié)果為:這些程序產(chǎn)生同樣的輸出。運(yùn)行時(shí)間是:

格式化方法 示例語(yǔ)句 運(yùn)行時(shí)間
簡(jiǎn)單的輸出一個(gè)固定字符 System.out.print(s); 1.3秒
使用簡(jiǎn)單格式"+" String s = 字符+字符, System.out.print(s); 1.8秒
使用java.text包中的 MessageFormat 類(lèi)的對(duì)象方法 String s = fmt.format(values); System.out.print(s); 7.8秒
使用java.text包中的 MessageFormat 類(lèi)的靜態(tài)方法 7.8*1.3秒

最慢的和最快的大約是6比1。如果格式?jīng)]有預(yù)編譯第三種方法將更慢,使用靜態(tài)的方法代替:
第三個(gè)方法比前兩種方法慢很多的事實(shí)并不意味著你不應(yīng)該使用它,而是你要意識(shí)到時(shí)間上的開(kāi)銷(xiāo)。
在國(guó)際化的情況下信息格式化是很重要的,關(guān)心這個(gè)問(wèn)題的應(yīng)用程序通常從一個(gè)綁定的資源中讀取格式然后使用它。

方法 1,簡(jiǎn)單的輸出一個(gè)固定的字符串,了解固有的I/O開(kāi)銷(xiā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
";
        System.out.print(s);
      }
    }
}
方法2,使用簡(jiǎn)單格式"+":
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 + "
";
        System.out.print(s);
      }
    }
}
方法 3,第三種方法使用java.text包中的 MessageFormat 類(lèi)的對(duì)象方法:
import java.text.*;
 public class format3 {
   public static void main(String args[]) {
     MessageFormat fmt =
      new MessageFormat("The square of {0} is {1}
");
      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);
     }
    }
}
方法 4,使用MessageFormat.format(String, Object[]) 類(lèi)的靜態(tài)方法
import java.text.*;
  public class format4 {
    public static void main(String args[]) {
      String fmt = "The square of {0} is {1}
";
      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);
      }
    }
  }

這比前一個(gè)例子多花費(fèi)1/3的時(shí)間。

隨機(jī)訪問(wèn)的性能開(kāi)銷(xiāo)

RandomAccessFile 是一個(gè)進(jìn)行隨機(jī)文件I/O(在字節(jié)層次上)的類(lèi)。這個(gè)類(lèi)提供一個(gè)seek方法,和 C/C++ 中的相似,移動(dòng)文件指針到任意的位置,然后從那個(gè)位置字節(jié)可以被讀取或?qū)懭搿?br>seek方法訪問(wèn)底層的運(yùn)行時(shí)系統(tǒng)因此往往是消耗巨大的。一個(gè)更好的代替是在RandomAccessFile上建立你自己的緩沖,并實(shí)現(xiàn)一個(gè)直接的字節(jié)read方法。read方法的參數(shù)是字節(jié)偏移量(>= 0)。這樣的一個(gè)例子是:
這個(gè)程序簡(jiǎn)單的讀取字節(jié)序列然后輸出它們。
適用的情況:如果有訪問(wèn)位置,這個(gè)技術(shù)是很有用的,文件中的附近字節(jié)幾乎在同時(shí)被讀取。例如,如果你在一個(gè)排序的文件上實(shí)現(xiàn)二分法查找,這個(gè)方法可能很有用。
不適用的情況:如果你在一個(gè)巨大的文件上的任意點(diǎn)做隨機(jī)訪問(wèn)的話就沒(méi)有太大價(jià)值。

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);
      }
    }
  }
壓縮的性能開(kāi)銷(xiāo)

Java提供用于壓縮和解壓字節(jié)流的類(lèi),這些類(lèi)包含在java.util.zip 包里面,這些類(lèi)也作為 Jar 文件的服務(wù)基礎(chǔ) ( Jar 文件是帶有附加文件列表的 Zip 文件)。
壓縮的目的是減少存儲(chǔ)空間,同時(shí)被壓縮的文件在IO速度不變的情況下會(huì)減少傳輸時(shí)間。
壓縮時(shí)候要消耗CPU時(shí)間,占用內(nèi)存。
壓縮時(shí)間=數(shù)據(jù)量/壓縮速度。
IO傳輸時(shí)間=數(shù)據(jù)容量/ IO速度。
傳輸數(shù)據(jù)的總時(shí)間=壓縮時(shí)間+I(xiàn)/O傳輸時(shí)間
壓縮是提高還是損害I/O性能很大程度依賴(lài)你的硬件配置,特別是和處理器和磁盤(pán)驅(qū)動(dòng)器的速度相關(guān)。使用Zip技術(shù)的壓縮通常意味著在數(shù)據(jù)大小上減少50%,但是代價(jià)是壓縮和解壓的時(shí)間。一個(gè)巨大(5到10 MB)的壓縮文本文件,使用帶有IDE硬盤(pán)驅(qū)動(dòng)器的300-MHz Pentium PC從硬盤(pán)上讀取可以比不壓縮少用大約1/3的時(shí)間。
壓縮的一個(gè)有用的范例是向非常慢的媒介例如軟盤(pán)寫(xiě)數(shù)據(jù)。使用高速處理器(300 MHz Pentium)和低速軟驅(qū)(PC上的普通軟驅(qū))的一個(gè)測(cè)試顯示壓縮一個(gè)巨大的文本文件然后在寫(xiě)入軟盤(pán)比直接寫(xiě)入軟盤(pán)快大約50% 。
下面的程序接收一個(gè)輸入文件并將之寫(xiě)入一個(gè)只有一項(xiàng)的壓縮的 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]);
    }
  }

下一個(gè)程序執(zhí)行相反的過(guò)程,將一個(gè)假設(shè)只有一項(xiàng)的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]);
    }
  }
高速緩存

關(guān)于硬件的高速緩存的詳細(xì)討論超出了本文的討論范圍。但是在有些情況下軟件高速緩存能被用于加速I(mǎi)/O??紤]從一個(gè)文本文件里面以隨機(jī)順序讀取一行的情況,這樣做的一個(gè)方法是讀取所有的行,然后把它們存入一個(gè)ArrayList (一個(gè)類(lèi)似Vector的集合類(lèi)):

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 方法被用來(lái)獲取任意行。這個(gè)技術(shù)是很有用的,但是很明顯對(duì)一個(gè)大文件使用了太多的內(nèi)存,因此有局限性。一個(gè)代替的方法是簡(jiǎn)單的記住被請(qǐng)求的行最近的100 行,其它的請(qǐng)求直接從磁盤(pán)讀取。這個(gè)安排在局域性的訪問(wèn)時(shí)很有用,但是在真正的隨機(jī)訪問(wèn)時(shí)沒(méi)有太大作用?
分解
分解 是指將字節(jié)或字符序列分割為像單詞這樣的邏輯塊的過(guò)程。Java 提供StreamTokenizer 類(lèi), 像下面這樣操作:

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);
      }
    }
  }

這個(gè)例子分解小寫(xiě)單詞 (字母a-z)。如果你自己實(shí)現(xiàn)同等地功能,它可能像這樣:

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);
      }
    }
  }

第二個(gè)程序比前一個(gè)運(yùn)行快大約 20%,代價(jià)是寫(xiě)一些微妙的底層代碼。
StreamTokenizer 是一種混合類(lèi),它從字符流(例如 BufferedReader)讀取, 但是同時(shí)以字節(jié)的形式操作,將所有的字符當(dāng)作雙字節(jié)(大于 0xff) ,即使它們是字母字符。

串行化

串行化 以標(biāo)準(zhǔn)格式將任意的Java數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為字節(jié)流。例如,下面的程序輸出隨機(jī)整數(shù)數(shù)組:

  import java.io.*;
  import java.util.*;
  public class serial1 {
    public static void main(String args[]) {
      ArrayList al = new ArrayList();
      Random rn = new Random();
      final int N = 100000;
      for (int i = 1; i <= N; i++)
        al.add(new Integer(rn.nextInt()));
      try {
        FileOutputStream fos = new FileOutputStream("test.ser");
        BufferedOutputStream bos =  new BufferedOutputStream(fos);
        ObjectOutputStream oos =  new ObjectOutputStream(bos);
        oos.writeObject(al);
        oos.close();
      }
      catch (Throwable e) {
        System.err.println(e);
      }
    }
  }

而下面的程序讀回?cái)?shù)組:

import java.io.*;
 import java.util.*;
  public class serial2 {
    public static void main(String args[]) {
      ArrayList al = null;
      try {
        FileInputStream fis = new FileInputStream("test.ser");
        BufferedInputStream bis = new BufferedInputStream(fis);
        ObjectInputStream ois = new ObjectInputStream(bis);
        al = (ArrayList)ois.readObject();
        ois.close();
      }
      catch (Throwable e) {
        System.err.println(e);
      }
    }
  }

注意我們使用緩沖提高I/O操作的速度。
有比串行化更快的輸出大量數(shù)據(jù)然后讀回的方法嗎?可能沒(méi)有,除非在特殊的情況下。例如,假設(shè)你決定將文本輸出為64位的整數(shù)而不是一組8字節(jié)。作為文本的 長(zhǎng)整數(shù)的最大長(zhǎng)度是大約20個(gè)字符,或者說(shuō)二進(jìn)制表示的2.5倍長(zhǎng)。這種格式看起來(lái)不會(huì)快。然而,在某些情況下,例如位圖,一個(gè)特殊的格式可能是一個(gè)改 進(jìn)。然而使用你自己的方案而不是串行化的標(biāo)準(zhǔn)方案將使你卷入一些權(quán)衡。
除了串行化實(shí)際的I/O和格式化開(kāi)銷(xiāo)外(使用DataInputStream和 DataOutputStream), 還有其他的開(kāi)銷(xiāo),例如在串行化恢復(fù)時(shí)的創(chuàng)建新對(duì)象的需要。
注意DataOutputStream 方法也可以用于開(kāi)發(fā)半自定義數(shù)據(jù)格式,例如:

import java.io.*;
  import java.util.*;
  public class binary1 {
    public static void main(String args[]) {
      try {
        FileOutputStream fos = new FileOutputStream("outdata");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        DataOutputStream dos = new DataOutputStream(bos);
        Random rn = new Random();
        final int N = 10;
        dos.writeInt(N);
        for (int i = 1; i <= N; i++) {
          int r = rn.nextInt();
          System.out.println(r);
          dos.writeInt(r);
        }
        dos.close();
      }
      catch (IOException e) {
        System.err.println(e);
      }
    }
  }

和:

 import java.io.*;
  public class binary2 {
    public static void main(String args[]) {
      try {
        FileInputStream fis = new FileInputStream("outdata");
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream dis = new DataInputStream(bis);
        int N = dis.readInt();
        for (int i = 1; i <= N; i++) {
          int r = dis.readInt();
          System.out.println(r);
        }
        dis.close();
      }
      catch (IOException e) {
        System.err.println(e);
      }
    }
  }

這些程序?qū)?0個(gè)整數(shù)寫(xiě)入文件然后讀回它們

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/67227.html

相關(guān)文章

  • JAVA 中原生的 socket 通信機(jī)制

    摘要:采用標(biāo)準(zhǔn)的傳輸格式,就能進(jìn)行請(qǐng)求響應(yīng)了某些特定的框架,可能會(huì)有自定義的通信格式。對(duì)于這種情況,采用多線程的模型再合適不過(guò)。只啟動(dòng)固定的線程數(shù)來(lái)進(jìn)行處理,既利用了多線程的處理,又控制了系統(tǒng)的資源消耗。在的包中,提供了相應(yīng)的實(shí)現(xiàn)。 JAVA 中原生的 socket 通信機(jī)制 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)保留出處:https://github.com/jasonGeng88/blog...

    Eric 評(píng)論0 收藏0
  • Java進(jìn)階之路 - 收藏集 - 掘金

    摘要:請(qǐng)欣賞語(yǔ)法清單后端掘金語(yǔ)法清單翻譯自的,從屬于筆者的入門(mén)與實(shí)踐系列。這篇一篇框架整合友好的文章三后端掘金一理論它始終是圍繞數(shù)據(jù)模型頁(yè)面進(jìn)行開(kāi)發(fā)的。 RxJava 常用操作符 - Android - 掘金 原文地址 http://reactivex.io/documenta... ... RxJava 和 Retrofit 結(jié)合使用完成基本的登錄和注冊(cè)功能 - Android - 掘...

    BakerJ 評(píng)論0 收藏0
  • 高并發(fā) - 收藏集 - 掘金

    摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類(lèi)的相關(guān)原理,java.util.concurrent包中很多類(lèi)都依賴(lài)于這個(gè)類(lèi)所提供的隊(duì)列式...

    levius 評(píng)論0 收藏0
  • 高并發(fā) - 收藏集 - 掘金

    摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類(lèi)的相關(guān)原理,java.util.concurrent包中很多類(lèi)都依賴(lài)于這個(gè)類(lèi)所提供的隊(duì)列式...

    fantix 評(píng)論0 收藏0
  • 看透 Spring MVC 源代碼分析與實(shí)踐 —— 網(wǎng)站基礎(chǔ)知識(shí)

    摘要:兩個(gè)序號(hào),三個(gè)標(biāo)志位含義表示所傳數(shù)據(jù)的序號(hào)。正常通信時(shí)為,第一次發(fā)起請(qǐng)求時(shí)因?yàn)闆](méi)有需要確認(rèn)接收的數(shù)據(jù)所以為。終止位,用來(lái)在數(shù)據(jù)傳輸完畢后釋放連接。手機(jī)網(wǎng)站如,填寫(xiě)。中的用法普通的用法分為和兩大類(lèi)。 網(wǎng)站架構(gòu)及其演變過(guò)程 基礎(chǔ)結(jié)構(gòu) 網(wǎng)絡(luò)傳輸分解方式: 標(biāo)準(zhǔn)的 OSI 參考模型 TCP/IP 參考模型 showImg(https://segmentfault.com/img/remot...

    mingde 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<