【问题标题】:RandomAccessFile readIntRandomAccessFile readInt
【发布时间】:2010-12-02 16:45:26
【问题描述】:

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

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

怎么解决???

扫描仪不是个好主意,因为文件包含超过 10 亿个数字......这需要很长时间......

是的,文本文件。

文件包含数字分隔的空格符号。例如(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

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

【问题讨论】:

  • 关键问题,数据是二进制还是文本格式?您的问题不清楚。

标签: java file-io performance


【解决方案1】:

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

你可以通过order方法改变ByteBuffer的字节顺序。

【讨论】:

  • 内存映射数据时也可以使用ByteBuffer。
【解决方案2】:

如果您想随机访问数据,您需要能够确定从哪里开始和从哪里结束。对于文本格式,这可能会很棘手,您可能必须阅读所有前面的行/文本才能找到您想要的。

使用二进制格式,您可能能够准确计算出您想读取的位置,但您需要知道数字是如何编码的。例如是大端还是小端?

扫描仪可能不是最适合文本,对二进制数据无用,但如果速度可能足够快。

扫描大文件所花费的大部分时间是读取磁盘所花费的时间(假设它不适合内存),如果文件压缩良好,您可以显着加快这一速度,例如充满数字的文本确实如此。如果压缩它可能只需要 2 秒,而不是花 20 秒来阅读。 (它可能适合 OS 文件缓存)

【讨论】:

    【解决方案3】:

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

    我想简短的回答是:无论哪种方式,您都必须知道数字从哪里开始和在哪里结束,它是以文本形式还是二进制形式存储的,如果是二进制形式,字节顺序是什么,即小端或大端。

    如果存储为文本,则从数字构建一个字符串,然后对该字符串调用 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;
    

    【讨论】:

    • Vachovsky:你明白你的阅读方式取决于文件的编写方式吗?如果文件是以文本形式编写的,则不能只决定以二进制形式读取文件,反之亦然。
    【解决方案4】:

    如果您的数字存储为文本 readInt() 将不起作用。你必须解析文件,这是唯一的方法。

    【讨论】:

      猜你喜欢
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-04
      相关资源
      最近更新 更多