从/向文件读/写数组的最快方法?

时间:2012-09-11 18:31:55

标签: java arrays file io

我知道这里和网上有几个类似的线程但我似乎做错了什么。我的任务很简单 - 将一大堆整数(int []或ArrayList或你认为最好的)写入(并稍后读取)到文件中。越快越好。我的具体数组中有大约4.5M的整数,目前的时间是例如(以ms为单位):

  • 生成特里:14851.13071
  • 生成数组:2237.4661619999997
  • 保存阵列:89250.167617
  • 装载阵列:114908.08185799999

这是不可接受的,我想时间应该低得多。我究竟做错了什么?我不需要世界上最快的方法,但是这些时间大约需要5到15秒(不太受欢迎但不是强制性的)是我的目标。

我目前的代码:

long start = System.nanoTime();

Node trie = dawg.generateTrie("dict.txt");
long afterGeneratingTrie = System.nanoTime();
ArrayList<Integer> array = dawg.generateArray(trie);
long afterGeneratingArray = System.nanoTime();

try
{
    new ObjectOutputStream(new FileOutputStream("test.txt")).writeObject(array);
}
catch (Exception e)
{
    Logger.getLogger(DawgTester.class.getName()).log(Level.SEVERE, null, e);
}
long afterSavingArray = System.nanoTime();

ArrayList<Integer> read = new ArrayList<Integer>();
try
{
    read = (ArrayList)new ObjectInputStream(new FileInputStream("test.txt")).readObject();
}
catch (Exception e)
{
    Logger.getLogger(DawgTester.class.getName()).log(Level.SEVERE, null, e);
}
long afterLoadingArray = System.nanoTime();

System.out.println("Generating trie: " + 0.000001 * (afterGeneratingTrie - start));
System.out.println("Generating array: " + 0.000001 * (afterGeneratingArray - afterGeneratingTrie));
System.out.println("Saving array: " + 0.000001 * (afterSavingArray - afterGeneratingArray));
System.out.println("Loading array: " + 0.000001 * (afterLoadingArray - afterSavingArray));

2 个答案:

答案 0 :(得分:3)

不要使用java Serialization。它非常强大和强大,但不是特别快速(或紧凑)。使用简单的DataOutputStream并致电writeInt()。 (请确保在BufferedOutputStreamDataOutputStream之间使用FileOutputStream

如果要在读取时预先调整数组大小,请将第一个int写为数组长度。

答案 1 :(得分:0)

以下内容可能是一个相当快的选择。如果您担心的是减少开销,您还应该使用实际的数组int[]而不是ArrayList<Integer>

final Path path = Paths.get("dict.txt");
...
final int[] rsl = dawg.generateArray(trie);
final ByteBuffer buf = ByteBuffer.allocateDirect(rsl.length << 2);

final IntBuffer buf_i = buf.asIntBuffer().put(rsl).flip();
try (final WritableByteChannel out = Files.newByteChannel(path,
    StandardOpenOptions.WRITE, StandardOpenOptions.TRUNCATE_EXISTING)) {
  do {
    out.write(buf);
  } while (buf.hasRemaining());
}

buf.clear();
try (final ReadableByteChannel in = Files.newByteChannel(path,
    StandardOpenOptions.READ)) {
  do {
    in.read(buf);
  } while (buf.hasRemaining());
}
buf_i.clear();
buf_i.get(rsl);