[转载]如何在Android中定义容量巨大的数组-czxttkl-搜狐博客!!!

baacloud免费翻墙vpn注册使用

来源: [转载]如何在Android中定义容量巨大的数组-czxttkl-搜狐博客!!!

背景:

本人因为某Android项目需要,需要在Android中定义一个容量为2万的float数组。这两万个float值已经存在某个文件中。
方法:
1.直接在Java文件里定义?
Java单个函数的长度限制为65535字节(不确定具体数值,但肯定是有限制的)。故在Java文件中直接定义如此之长的数组是行不通的。
2. BufferedReader 或是 Scanner?
可以创建一个文件,每行存放一个float值。通过BufferedReader.nextLine()读取每一行的字符,用Float.parseFloat(String)来将读到的字符转换成float值,最后将float值存取至数组里。也可以通过Scanner.nextFloat()这样的方法来读取文件中存放的float值。这个时候,文件里并不需要将每个float值放在单独的一行里。但是不同的float值至少需要以某些符号隔开(例如,空格)。
经 过对比,通过BufferedReader读取2W个float值比较快,使用Scanner会占用大量内存,并且不断调用GC,导致线程暂停。但是,当 要读取的文件很大的时候,即使使用BufferedReader也会出现问题:在低端的机子上运行时,Logcat会出现OutOfMemory的错误提 示。
3. 将2万个float值写入文件后做Java的内存映射。
Java内存映射网上的文章不多,可以参考:http://www.javacodegeeks.com/2013/05/power-of-java-memorymapped-file.htmlhttp://www.studytrails.com/java-io/Channels.jsp。这种方法,需要先将所有float值以byte的形式写入到文件中。接着,使用FileChannel将文件中的byte映射到内存中,生成FloatBuffer。最后在FloatBuffer中读取float值存至float数组中。在通过经测试,这种方法比BufferedReader快很多。但是如果算上写文件的时间的话,不如BufferedReader来得方便。
大家可以借鉴一下我测试对比所用的源码。第一个部分,我使用Scanner;第二个部分,我使用BufferedReader;第三部分,我将第二部分读取到的float值以byte形式存取至文件中;第四部分,我使用MappedByteBuffer将文件中的内容映射至内存,并生成新的float数组。
源码下载地址:https://db.tt/9jCbO653
以下是结果运行截图:

当然,以上测试程序均在PC java端运行。真正要移植到Android上进行内存映射,还需要:
1. 由于从assets里读文件只能获取InputStream,而调用FileChannel.map()必须从FileInputStream中获得,故需要将assets里的内存映射文件转移至sd卡上后再从sd卡上读取它们。
2. 在测试文件中,我使用了DataOutputStream.writeFloat()将float数组写入内存映射文件。该方法写入遵循 BIG_ENDIAN规则。故当进行内存映射的时候,很有可能是以LITTLE_ENDIAN的方法读取的(这还要看你是如何实现内存映射的)。
以下这段代码,给出了如何将一个存好的float数组(cubeTextureCoordinateData)以LITTLE_ENDIAN的方式写入内存映射文件:
/* Writing Memory Map Raw Data */
ByteBuffer littleEndian = ByteBuffer.allocateDirect(11160 * 4).order(ByteOrder.LITTLE_ENDIAN);
i = 0;
while (i < 11160) {
littleEndian.putFloat(cubeTextureCoordinateData[i++]);
}
littleEndian.flip();

try {
FileOutputStream fos = new FileOutputStream(“memorymap_texture_little_endian”);
FileChannel fc = fos.getChannel();
fc.write(littleEndian);
fc.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}

鸣谢北邮编程浪子张亚杰在内存映射上的支持。
赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏