I have function to read image file az byte array.
Performance analisys gives to me interesting facts.
I have check if file exists and then read as byte array.
File.exists spent 69.7% of time in function ?????
Open read and close spent only 30,3% of time.
I cant't explaint to mysefl why?
Is this depend on something or it is default behaviour?
If this check is always slow - may be better approach is to open file without check for existing. And of cource use catch to solve case with missing file.
UPDATE:
Files are stored in internal SD card. More than 20000 files.
When test with 30 files percent is reduced to 23%.
Finally I'm using file open without check 'exists'. Working with files I have to catch exceptions - so my code security isn't compromised.
Related
I need to read binary file from asset folder in my app, and the way I'm trying to do it is by obtaining Channel:
AssetFileDescriptor assetFd = context.getAssets().openFd("file.db");
FileChannel fileChan = assetFd.createInputStream().getChannel();
The problem is that AssetManager, AssetFileDescriptor are very poorly documented classes and behave in unpredicted manner (as it seems to me). For example, if you will try to obtain fileChan.position() immediately after code above you won't get 0, in my case it'll be 976. After digging through StackOverflow I found out that it's normal behaviour and you need to be aware that assets are compressed into some internal binary form and AssetFileDescriptor isn't real file descriptor.
In my case I have a file structure with absolute byte positions stored in a header, so it seems like to read it properly I also need take into account assetFd.getStartOffset().
Also I've got zero clue about method AssetFileDescriptor.createInputStream behaviour after reading its doc:
This will either return a full asset AssetFileDescriptor.AutoCloseInputStream, or an underlying ParcelFileDescriptor.AutoCloseInputStream depending on whether the the object represents a complete file or sub-section of a file.
Lack of understanding whole picture and documentation makes me nervous about using this approach.
Should I be worried about AssetFileDescriptor.createInputStream behaviour when reading big files (over 1mb)? Is it safe to use Channels when reading asset files?
Thank you in advance!
The best way to deal with assets is to copy them to the internal or external storage and then read them with whatever method you want.
Thanks to #pskink for help!
FileUtils.copyDirectory doesn't write date modified correctly unless the Android SD card is unmounted. Using this simple bit of code from FileUtils:
try {
FileUtils.copyDirectory(srcDir2, destDir2);
} catch (IOException e) {
I can copy a directory from the internal storage on the phone to the sd card preserving the date modified information on the files in the directory which is essential for my app.
Sadly if the SD card is removed without ejecting it all the date modified information on the files in the copied dir is set to the time the files were copied. if the SD is unmounted correctly then the date modified information is preserved correctly.
I have tried the flush and close functions but they are not relevant to this kind of file. What code am I missing to finalize the directories without unmounting? I am using an android device will a full size SD slot and I cant risk loosing all the information if it gets knocked out without a proper eject
There's a version of this method that accepts a flag as third parameter to try to control the date of last modification. You can check the docs here. But looks like the method you are using also tries to preserve the date by default. In fact, reading the source code, the method you are using just calls this method with the third parameter set to true.
In the docs for your method it is said:
Note: This method tries to preserve the files' last modified date/times using File.setLastModified(long), however it is not guaranteed that those operations will succeed. If the modification operation fails, no indication is provided.
In the end what this library does each time it copies a file or dir is to call File.setLastModified over the destination file with the last modified date of the source file. This method has been reported to be unreliable in Android, as you can see in these other questions:
Android set last modified time for the file
file.lastModified() is never what was set with file.setLastModified()
Is it possible to reset the last modified date of an Android file?
But in your case, I think you are trying to provide a workaround for something that is just designed that way. I'm no expert, but this is managed by either the OS or the FileSystem. The unmounting mechanism serves a purpose, I think you can't do much about it as an app developer.
I have a file on android phone which I would like to securely wipe it.
I read this.
It mentions This is especially true on mobile devices containing flash, which has wear-leveling to prolong its life and isn't guaranteed to overwrite the same block internally when you overwrite a block on the filesystem.
So, if I would to use the code on.Would it securely wiped on android phone ? Or when I use RandomAccessFile to write data to the file, it would be on a new block instead of the original block ?
Is it totally 100% impossible to get known of the exact block pointer on android ?
Or I have to recursively create a file, write with random data until the storage space hits the max. Then I try to edit the file I wish to delete. Which the flash will be force to use the original block while I rewrite the content and delete it.
Try to read the documentation about the Objects and Methods used in the code you mentioned This , nothing points that you write over the real Blocks used to save the file, and note the file can be written in Non-Sequential blocks, i think my friend told me about article discuss this issue, and they solved it using C++.
I'm developing for Android 2.2.
Things put to res and assets are compressed in the APK by default unless their extension indicates that they're already compressed (mp3, png). Moreover, before Android 2.3, to assets, you could only put uncompressed files of size less than 1 MB.
Question 1:
if I put a 1.5MB binary file to res/raw, and my program refers to it with its standard Android ID (R.raw.....), then will the system pull the whole file into memory? Since the 1.5MB is stored in a compressed way, I suppose it must. This is unpleasant because it is possible that the program only needs 1KB of data to be loaded from a given file offset. This can have a serious impact on app performance/speed.
I see two solutions:
(hack) Use mp3 or png extensions; but I am not sure this allows memory-efficient access after all (i.e. inputstream.skipbytes, etc.)
After the installation, at the first start of the app, the app will copy the files to its own writable working folder (in SD card). Since this point, it will always access the files from there instead of the R.raw... way. Therefore, the sequential read will work for sure, i.e. the memory usage will be no more than the actual data read from the specified file offset (apart from temporary read buffers used by inputstream.seek implementation, which are well-optimized i.e. small I suppose).
Question 2:
what is the best way of reading binary data memory-efficiently, from big files? I don't want to split my big files into many small ones unless that's the only way.
I'd go with #2 solution and then would use RandomAccessFile to avoid linear access.
I also would to opt for solution #2, but instead of using random access file, I would use java.nio.MappedByteBuffer - this way you will get fast random access with byte buffer semantic.
I'm writing a purge function for our software that removes all image files that haven't been used in over a month. To do this, I am checking two things:
the last-modified date of the file
a query on a database that shows recently viewed files.
The query is much slower than the file check. So I would ideally like to be able to reset the last modified date on any files that fail the first check, but pass the second, so that (for example) a list of venerable but often-used files aren't gradually increasing the processing load of the management system.
Is there a way to do this without recourse to something crude (and possibly even slower), like renaming each file to a temporary label, then itself?
As Nik said the setLastModified() method on the File class may not always work depending where you are in the Android file system. If on the SD Card then some devices will return false from that call and thus not change the date.
There are more details about it here:
http://code.google.com/p/android/issues/detail?id=1992
http://code.google.com/p/android/issues/detail?id=1699
Plus some other stackoverflow thread here:
file.lastModified() is never what was set with file.setLastModified()
setLastModified() is a standard method on any Java File object that you can use to update this value.
SDK Documentation.