5

I have implemented a data structure which is working on my computer and now I am trying to port it into my android application. I open a raw .dat resource and get a InputStream but I need to get a FileInputStream:

FileInputStream fip = (FileInputStream) context.getResources().openRawResource(fileID);
FileChannel fc = fip.getChannel();
long bytesSizeOfFileChannel = fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0L, bytesSizeOfFileChannel);
...

The code above throws the following exception since an InputStream can not be cast to a FileInputStream but that's just what I need:

java.lang.ClassCastException: android.content.res.AssetManager$AssetInputStream cannot be cast to java.io.FileInputStream

All my code is build on using this FileChannel with a FileInputStream so I want to keep using it. Is there a way to go from having an InputStream from context.getResources().openRawResource(fileID) and then convert it into a FileChannel?


Somewhat relevant posts in which I could not find a working solution for my case which android:

How to convert InputStream to FileInputStream

Converting inputStream to FileInputStream?

Using FileChannel to write any InputStream?


Community
  • 1
  • 1
Joop
  • 3,706
  • 34
  • 55
  • 2
    no, resource files are not "normal" files, that is they dont exist in a file system – pskink May 09 '15 at 10:41
  • I have been working 2 weeks on this. If I can't get this to work I will laugh for atleast 2 more weeks. – Joop May 09 '15 at 10:43
  • 1
    why can't you just use InputStream ? – pskink May 09 '15 at 10:43
  • My whole purpose was to create a data-structure that was as fast as humanly possible in Java. Or atleast the best to my abilities. I read this article http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly#FileChannelwithMappedByteBufferandbytearraygets which states that the method I use is the fastest. That's why I implemented it in this way. – Joop May 09 '15 at 10:45
  • At best, the article states that using `MappedByteBuffer` is the fasted for the Java 6 JVM when reading in a file. Android is not running the Java 6 JVM and you are not reading in a file. Android runs either the Dalvik VM or uses ART (depends on Android version) and you are reading in an asset (which is basically an entry in a ZIP file). The contents of that article are largely irrelevant. – CommonsWare May 09 '15 at 11:01
  • Fair points. Too bad it took me 2 weeks to find out. – Joop May 09 '15 at 11:05

2 Answers2

6

A resource isn't a file. Ergo it can't be used as a memory-mapped file. If you have resources that are so enormous they need to be memory-mapped, they probably shouldn't be resources at all. And if they are small, memory mapping brings no advantages.

user207421
  • 305,947
  • 44
  • 307
  • 483
-1

This might be late, but i think you can indirectly get a FileInputStream from an InputStream. what i suggest is this: get the input stream from resource, then create a temp file,get a FileOutputStream from it. read the InputStream and copy it to FileOutputStream.

now the temp file has the contents of your resource file, and now you can create a FileInputStream from this file.

I don't know if this particular solution is useful to you, but i think it can be used in other situations. As an example, if your file is in the assets folder, you get an InputStream and then a FileInputStream using this method:

InputStream is=getAssets().open("video.3gp");
File tempfile=File.createTempFile("tempfile",".3gp",getDir("filez",0));

FileOutputStream os=newFileOutputStream(tempfile);
byte[] buffer=newbyte[16000];
int length=0;
while((length=is.read(buffer))!=-1){
os.write(buffer,0,length);
}

FileInputStream fis=new FileInputStream(tempfile);
vikrant
  • 2,169
  • 1
  • 21
  • 27