如何使用Java + LibGDX高效读取浮点数文本文件?

4

我正在使用Java/LibGDX编写一个小型的科学数据可视化应用程序。该应用程序首先读取描述4D数组的文本文件:

188 225 3 6 0.001 -0.023 1.345 2.475 ... 4.327

第一个四个整数指定了数组的维度:188 x 255 x 3 x 6,后面跟着大约760000个数字。总体而言,这个文本文件占用约5MB的空间。
这个4D数组代表了一个188像素高、255像素宽、带有3个颜色通道(RGB)的“扩充”图像。与常规RGB图像中仅有一个参数不同,每个像素通道都有6个“参数”。
我使用了下面从官方文档中复制过来的方式将以空格分隔的列表读入内存:
FileHandle ptmFile = Gdx.files.internal(filename);
String ptmText= ptmFile.readString();

然后我创建了一个简单的封装类AugPixel,它实际上是每个像素的6元素数组的包装器。我使用Scanner从字符串中读取和解析每个数字(请原谅我使用的半伪代码):

Scanner scan = new Scanner(ptmText);
int nRows = scan.nextInt();
int nCols = scan.nextInt();
int nColors = scan.nextInt();
int nParams = scan.nextInt();


AugPixel[][][] im = new AugPixel[nRows][nCols][nColors];

for (i = 1~nRows)
  for (j = 1~nCols)
    for (k = 1~nColors)
      im[i][j][k] = new AugPixel(nParams);
      for (m = 1~nParams) 
        im[i][j][k].addParam(scan.nextFloat());

这种方法在桌面版本中效果很好。加载文件并构建所有AugPixel对象大约需要5秒钟。然而,当我将应用程序移动到实际的Android设备(Nexus 7 32G(第二代))时,加载过程需要5分钟!

所以我的问题是:有没有办法加快加载速度?我可以自由地重新定义文件的组织方式。

谢谢!


也许如果您首先将整个文件读入内存(可能使用Files.readAllBytes),然后再处理它,速度可能会更快。也许是因为访问太多小文件而导致速度变慢。 - noone
@noone 感谢您的评论。不幸的是,我认为我的当前程序已经在使用这种策略了。它调用FileHandle.readString()将整个文件一次性读入一个长字符串中,然后使用Scanner解析字符串中的每个数字。或者,也许我可以将浮点数存储为二进制数据而不是文本。我会看看那样是否可行。谢谢! - Mingjing Zhang
哦,我现在明白了,我错过了你的ptmFile.readString()的调用。也许你应该对程序进行分析以找出主要瓶颈所在。也许甚至是将760k个字符串转换为浮点数的问题。 - noone
是的,结果证明字符串转换是主要瓶颈。我现在去掉了那部分,加载时间令人满意。谢谢! - Mingjing Zhang
1个回答

0
如果从文件中读取数据是主要瓶颈,您可以尝试使用某种形式的异步IO,以便在加载其余部分时处理字符串的部分。
如果主要瓶颈是解析字符串,您可以尝试多线程处理过程或切换到二进制文件格式。如果您愿意放弃文本格式,则最佳解决方案可能是切换到二进制文件格式,这应该会大大减少处理时间并可能减小文件大小。

谢谢您的建议!我会调查一下,看看瓶颈在哪里。 - Mingjing Zhang
很有可能(你仍然应该进行分析),瓶颈在于字符串转换为浮点数。如果是这种情况,你可以像我建议的那样多线程处理,或者如果可能的话使用二进制文件。二进制文件将大幅减少处理时间(也许还能减小文件大小)。 - NitrogenReaction
你说得完全正确!原来字符串解析占用了大部分时间。现在我重新定义了二进制格式的文件,现在在Android设备上加载只需要一秒钟!非常感谢你的帮助! - Mingjing Zhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接