【问题标题】:Fastest way to read a large number from text file [duplicate]从文本文件中读取大量数字的最快方法[重复]
【发布时间】:2017-05-16 17:42:11
【问题描述】:

所以我有一个非常大的数字(1500 万位)存储在一个文本文件中,我正在使用这种方法来读取数字

 BufferedReader Br1 = null;
    StringBuilder Final = new StringBuilder("");

    System.out.println("Loading......");

    Br1 = new BufferedReader (new FileReader("NumberFind.txt"));
    String Line = Br1.readLine();
    while(Line != null) {
        Final.append(Line);
        Line = Br1.readLine();
    }
    sum1 = new BigInteger(Final.toString());
    Br1.close();
            System.out.println("Loaded");

这可行,但加载整个数字大约需要 45 分钟,有没有更快的方法来加载它?

【问题讨论】:

    标签: java file bufferedreader


    【解决方案1】:

    如果只有一个数字,您的文件只有 14.3 兆字节。我不知道 BufferedReader、BigInteger 等的什么怪癖会导致 45 分钟的负载,但它可能只是那个读行循环。您应该能够在几秒钟而不是几分钟内将整个文件读入内存。

    尝试在没有 BufferedReader 的情况下将整个文件(或者可能只是包含数字的部分)读入字符串。请参阅 FileReader.readAsBinaryString() 以完成此操作。

    将内存中的数字作为字符串保存后,您应该能够通过将字符串参数传递给它来构造一个新的 BigInteger,就像您在上面的代码示例中所做的那样。

    如果这不能解决所有问题,并且您希望获得更多见解,我建议您缩小 45 分钟延迟发生的范围。我猜它在你的行阅读循环中,但我可能是错的。如果您在某些环境中,例如嵌入式设备,在 CPU、磁盘读取时间等方面存在异常限制,这可能是一个因素。

    【讨论】:

    • 好的,这是我想出的代码,对吗? BufferedReader Br = new BufferedReader (new FileReader("test2.txt"));字符串线 = Br.readLine(); BigInteger number = new BigInteger(Line); System.out.println("完成");
    • 将文件转换为字符串似乎很快,但将字符串转换为 BigInteger 需要很长时间
    • 那么文件读取代码似乎没有导致延迟。您可能想要验证您正在阅读的行的预期长度(例如 console.log(Line.length) )约为 1500 万。但是假设您从文件中输入的内容包含预期的数字并且不需要很长时间,例如分钟,完成,那么罪魁祸首可能是 BigInteger(line)。但是该怎么办呢?唔。不确定。
    • 我想我会确认它是那条需要永远的特定行。如果是这样,请尝试其他一些大整数库,例如strint,查看另一个实现是否更快地解析非常大的字符串值。
    • 我仔细检查了长度,它是 17,112,422 ,而且我以前从未使用过 BigInteger 库,这是一个网站还是我可以在 eclipse 上下载的东西?
    【解决方案2】:

    可以创建具有文件大小的初始容量(可能减去行尾)的 StringBuilder。

    使用 BigInteger 而不是 StringBuilder 来累积结果可以节省大量内存。我不知道这是否确实更快。

    Path path = Paths.get("NumberFind.txt");
    BigInteger n = Files.lines(path)
            .reduce(// 1. the start value
                    BigDecimal.ZERO,
    
                    // 2. the accumulator adding the next line
                    (num, line) ->
                    num.scaleByPowerOfTen(line.length()).add(new BigDecimal(line)),
    
                    // 3. The combiner for a parallel stream (irrelevant)
                    (num1, num2) ->
                    num1.scaleByPowerOfTen(num2.toString().length()).add(num2))
            .toBigInteger();
    

    读取一行会将其转换为 BigDecimal。前面的行累加到一个 BigDecimal,然后必须乘以 10n,其中 n 是行长。

    我使用 BigDecimal,因为它有一个不错的 scaleByPowerOfTen。最后将 BigDecimal 转换为 BigInteger。

    此解决方案可能会更慢。我很好奇。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      • 1970-01-01
      相关资源
      最近更新 更多