RandomAccessFile readInt

时间:2010-12-02 16:45:26

标签: java file-io performance

如何从文件中读取数字???

当我使用readInt方法时,我得到一个大数字,它不等于文件中的数字。

如何修复???

扫描仪不是一个好主意,因为文件包含超过1000万个数字......这将花费很长时间......

是的,文本文件。

文件包含数字分隔的空格符号。例如(test.txt)

1 2 4 -4004 15458 8876


   public static void readByMemoryMappedFile(int buffer[], String filename) throws IOException
   {
      int count = 0;

      RandomAccessFile raf = new RandomAccessFile(filename, "r");
      try {
            MappedByteBuffer mapFile = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());

            StringBuilder b = new StringBuilder();
            try {
                  while (mapFile.hasRemaining()) {
                        byte read = mapFile.get();
                        if (read == ' ' && b.length() > 0) {
                              buffer[count++] = mapFile.getInt();//Integer.parseInt(b.toString());
                              b.delete(0, b.length());
                        } else {
                              b.append((char) read);
                        }
                  }
            } catch (BufferUnderflowException e) {
                  // Всё, файл закончился
            }
            if (b.length() > 0) {
                  buffer[count++] = Integer.parseInt(b.toString());
            }
      } finally {
            raf.close();
      }
   }

所以,我附上了报告:


// operation: time
reading: 39719   // t0
reading: 28297   // t1
reading: 56719   // t2
reading: 125735  // t3
reading: 199000  // t4

t0< t1< t2< t3< t4

如何改变程序的行为得到这个:t0~t1~t2~t3~t4 ???

4 个答案:

答案 0 :(得分:2)

大数字的可能原因可能是由于字节排序。从通道读取时,Java默认使用Big Endian。如果您正在读取的文件是Little Endian,那么小数字将变大,因为最低有效字节成为最重要的字节。

您可以使用order方法更改ByteBuffer的字节顺序。

答案 1 :(得分:1)

如果要随机访问数据,则需要能够确定从哪里开始以及在何处完成。对于文本格式,这可能很棘手,您可能必须阅读所有以前的行/文本以找到您想要的那个。

使用二进制格式,您可以精确计算要读取的位置,但需要知道数字的编码方式。例如它是大端还是小端?

扫描程序可能不是文本的最佳选择,对二进制数据可能没用,但是如果速度可能足够快。

扫描大文件所花费的大部分时间是读取磁盘所花费的时间(假设它不适合内存)如果文件压缩得很好,你可以大大加快速度,例如充满数字的文字呢。如果压缩,它可能只需要2秒钟,而不需要20秒读取。 (它可能适合OS文件缓存)

答案 2 :(得分:1)

这一切都取决于数字的存储方式。

我想简短的回答是:无论如何,你必须知道数字的开始位置和结束位置,以及它是以文本还是以二进制形式存储,如果以二进制形式存储,则字节顺序是什么,即little-endian或big-endian。

如果它以文本形式存储,则从数字构建一个String,然后在该String上调用Integer.parseInt。 (或者,对于其他数据类型,它是浮点数,Double.parseDouble等。)

如果它存储为二进制整数,则将字节读入数组,或逐个读取,然后乘以256的幂并加在一起。

例如,假设您有一个以小端顺序排列的四字节数字。您将其读入大小为4的字节数组中。然后:

byte[] incoming=new byte[4];
file.read(incoming);
int n=0;
for (int p=0;p<4;++p)
  n=n*256+incoming[p];
return n;

答案 3 :(得分:0)

如果您的号码存储为文本,则readInt()将无效。你必须解析文件,这是唯一的方法。