File Operations in Android NDK

前端 未结 5 1485
太阳男子
太阳男子 2020-11-28 03:14

I am using the Android NDK to make an application primarily in C for performance reasons, but it appears that file operations such as fopen do not work correctly in Android.

5条回答
  •  有刺的猬
    2020-11-28 03:45

    I can also verify that fopen() works correctly, but not if you're trying to access a file in the application's resources or assets folder. I recommend, to avoid having to reinvent the wheel, that you stick any assets you want shipped with your app in the assets folder, where they'll be packaged up for distribution.

    In the assets folder case you need to do one of two things, depending on whether the file was compressed by the packager. Both use the AssetManager methods, and you can get the AssetManager from the context/app. File names are always relative to the assets folder, btw: If your have a file "foo.png" directly in the assets folder, you'd open "foo.png," not something like "assets/foo.png".

    1. If the file wasn't compressed (i.e., it's one of the extensions that doesn't get compressed, like .png), you can get a file descriptor from AssetManager.openFd() and pass it to C++. Then you can use fdopen(dup(fd),"r"); to open the file as a FILE*. Note you must fseek() to the offset, and keep track of the length of the file yourself. You're really getting a file handle to the entire assets package, and your file of interest is only a small part.

    2. If your file is compressed, you need to use the Java streaming reader: AssetManager.open() gives you an InputStream you can use the read the file in. This is a PITA because you can't query (AFAIK) the file size; I run a preprocessing step on my assets folder that generates a list of all the files with their respective sizes so I can know, e.g., how big of a buffer to allocate.

    If your file is a resource, you may need to go through the Resource class to access it, though it appears resources are also packed into the same assets package. Resource has an openRawResource() call to get the InputStream and an openRawResourceFd() call to get the file descriptor, as above, though.

    Good luck.

提交回复
热议问题