首页 > 代码库 > ndk文件操作问题及小结
ndk文件操作问题及小结
最近在做文件传输,发现在android下用f系列的C库函数去读取文件文件大小会受到2G大小的约束,查阅了很久,最后只能去看google的libc源码,发现了以下几个问题:
1、bionic的libc是谷歌基于bsd开发的,大约200k左右,比gnu的libc小一半左右,也比uClibc小,谷歌应该不只是为了规避LGPL的静态链接约束才单独开发的,可能是为了效率问题;
2、gnu的ftello等系列函数一般可以用宏-D_FILE_OFFSET_BITS 64指定off_t的类型来控制函数是否支持2G以上的文件,也可以用_LARGEFILE_SOURCE来支持ftello64位之类的函数。但这些宏在ndk里失效,完全不可用。ftello64在bionic里是没有声明和定义的,有兴趣可以去看ftell.c的源码,所以_LARGEFILE_SOURCE失效。那么第一个宏为何也会失效呢?先看下其声明:
1 | off_t ftello( FILE *fp) |
然后追踪off_t的定义:
1 2 3 4 | #ifndef _OFF_T_DEFINED_ #define _OFF_T_DEFINED_ typedef __kernel_off_t off_t; #endif |
继续追踪__kernel_off_t,看其是否受宏-D_FILE_OFFSET_BITS的影响:
1 | typedef long __kernel_off_t; |
到这里就明了了,可能等谷歌出了64位的android系统才会支持ftello之类的64位c库函数吧。
既然存在以上的问题,那么如何读取2G以上的文件呢?其实可以绕开libc,用系统库函数,当然由于没有缓冲区,效率当然就低一些。谷歌提供了lseek64,配合read和write,就可以操作4G以上的文件了。看下lseek64的声明:
1 | extern off64_t lseek64( int , off64_t, int ); |
自己有兴趣可以追踪off64_t,其实就是long long。
虽然解决问题了,但我还是想拓展一下,bionic对部分posix风格支持的也不太好,如C++ exceptions和wide chars。其实ios也一样,都只是尽量支持,但不完全,所以我以前写了一个mmap跨平台程序在ios7以下版本正常,但在ios7直接崩溃,大家小心点就好。为了效率,还可以看看mmap如何操作大文件及效率对比。