java.util.Scanner是否慢?

在Android应用程序中,我想使用Scanner类从文本文件(它是OpenGL的顶点坐标列表)读取浮动列表。 确切的代码是:

Scanner in = new Scanner(new BufferedInputStream(getAssets().open("vertexes.off"))); final float[] vertexes = new float[nrVertexes]; for(int i=0;i<nrVertexFloats;i++){ vertexes[i] = in.nextFloat(); } 

看起来这是非常慢的(花费30分钟来读取10,000个浮点数!) – 在2.1模拟器上testing。 这是怎么回事? 我不记得当我在PC上使用Scanner时,Scanner会变得很慢(事实上,我从来没有读过超过100个值)。 或者是其他的东西,比如从资产inputstream中读取?

谢谢您的帮助!

不了解Android,但至less在JavaSE中,Scanner速度很慢。

在内部,扫描仪进行UTF-8转换,这是无用的浮动文件。

由于所有你想要做的是从文件读取浮动,你应该去与java.io包。

SPOJ的家伙们正在努力争取I / O速度。 这是一个非常棘手的问题的波兰编程竞赛网站。 他们的区别在于,他们接受比其他站点更广泛的编程语言,并且在他们的许多问题中,input是如此之大,以致于如果您不编写高效的I / O,您的程序将突破时间限制。

例如, 在这里查看他们的论坛,了解定制parsing器的想法。

当然,我build议不要写你自己的floatparsing器,但是如果你需要速度,那还是一个解决scheme。

正如其他海报所说,以二进制格式包含数据的效率更高。 不过,为了快速修复,我发现replace:

 scanner.nextFloat(); 

 Float.parseFloat(scanner.next()); 

几乎快了7倍。

为了给这个答案增加更多的信息,这个方法的性能问题的根源在于它使用一个正则expression式来search下一个float,如果你知道你正在读的数据的结构,这是不必要的。

原来大多数(如果不是全部的话) next*由于类似的原因使用正则expression式,所以如果你知道数据的结构,最好总是使用next()并parsing结果。 IE也使用Double.parseDouble(scanner.next())Integer.parseInt(scanner.next()) Double.parseDouble(scanner.next()) Integer.parseInt(scanner.next())

相关来源: https : //android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/util/Scanner.java

对于Spotify挑战,他们编写了一个用于更快parsingIO的小型Java工具: http : //spc10.contest.scrool.se/doc/javaio该实用程序名为Kattio.java ,使用BufferedReader,StringTokenizer和Integer.parseInt / Double.parseDouble /Long.parseLong读取数字。

非常有见地的职位。 通常当我使用Java时, Scanner在PC上是最快的。 当我尝试在Android上的AsyncTask使用它时,也是一样的。

我认为Android必须拿出替代扫描仪。 我正在使用scanner.nextFloat();scanner.nextDouble();scanner.nextInt(); 所有这些使我的生活变得糟糕。 在我追踪我的应用之后,发现肇事者隐藏起来。

我改变了Float.parseFloat(scanner.next()); 同样的Double.parseDouble(scanner.next());Integer.parseInt(scanner.next()); ,这肯定使我的应用程序相当快,我必须同意,可能会快60%

如果有人经历过相同的情况,请在这里发帖。 而且我也在寻找Scanner API的替代scheme,任何人都有明智的想法可以在阅读文件格式时出现在这里。

是的,我没有看到这样的事情。 我可以在桌面上用4秒钟的时间读取大约10M浮点数的数据,但是不能这样。

我试图想到其他的解释 – 它可能阻止从getAssets()读取inputstream? 我可能会尝试完全读取该资源,计时,然后看看需要多less额外的时间来扫描。

Scanner可能是问题的一部分,但您需要剖析您的代码才能知道。 替代品可能会更快。 这是一个简单的比较ScannerStreamTokenizer 基准 。

我得到了完全相同的问题。 花了10分钟阅读我的18 KB文件。 最后,我写了一个桌面应用程序,使用DataOutputStream将这些可读的数字转换为机器可读的格式。

结果是惊人的。

顺便说一句,当我追踪它时,大多数Scanner方法调用都涉及正则expression式,其实现由com.ibm.icu.**包(IBM ICU项目)提供。 这真是矫枉过正

String.format也是一样 。 在Android中避免它!