The following reads bytes in a file and writes these bytes as characters in another file using Writer
. I have extracted it from this discussion
String filePath = Display.getInstance().getDatabasePath("TestDB.db");
FileSystemStorage fss = FileSystemStorage.getInstance();
InputStream is = fss.openInputStream(filePath);
byte[] plainBytes = Util.readInputStream(is);
//encrypt database file content
Log.p("Starting file encryption...");
byte[] cipherByteArray = FilesCipher.encryptFile(plainBytes);
Log.p("Done encrypting file");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cipherByteArray);
String encryptedFilePath = fss.getAppHomePath() + "EncryptedDB.db";
Log.p("Writing to new a file started...");
try (Writer w = new OutputStreamWriter(fss.openOutputStream(encryptedFilePath), "ISO-8859-1")) {
int nextChar = byteArrayInputStream.read();
while (nextChar > -1) {
char[] charArray = {(char) nextChar};
w.write(charArray);
nextChar = byteArrayInputStream.read();
}
Log.p("Done writing to a new file");
} catch (Exception e) {
Log.p("Error " + e);
}
If file size of the file being read (Eg TestDB.db
) is small (less than 500KB), In Simulator & Device, the Writer
writes to the new file (Eg. EncryptedDB.db
) very fast.
If the file is large eg. 3MB
, In Simulator it's written very fast to the new file. But in a device it takes more than 2 minutes
. I tested in Android 10.
I have confirmed that encryption is very fast since even when file is large, Log.p("Writing to new a file started...");
is executed within 2 Seconds
even in the device.
When file is large, in a Simulator Log.p("Done writing to a new file");
is executed within seconds but in a device it takes more than 3 minutes
. This means Writer
is slow in a device.
Writer
doesn't have a function to write bytes directly.
How can Writer
speed be enhanced in devices?
Writing/reading a single character has always been slow. You need to use a buffer and read with power of two multiples (our default is 8192 if I recall correctly).
You're allocating a single character array 3M times on a device... The fact that it runs reasonably well on a desktop is amazing.
I think the writing is the most important part here:
// before the loop
char[] charArray = new char[cipherByteArray.length];
int size = 0;
int nextChar = byteArrayInputStream.read();
// in the loop code...
while (nextChar > -1) {
charArray[size] = (char)nextChar;
size++;
if(size == charArray.length) {
w.write(charArray);
size = 0;
}
nextChar = byteArrayInputStream.read();
}
// then after the loop is complete...
if(size > 0) {
w.write(charArray, 0, size);
}
This absolutely enhances Writer
speed. A file of size 11.9MB
(It has images stored as blob
), results to the following log in Android Studio. Encryption completes in 3 sec
& writes to the new file in 1 sec
2024-07-28 11:03:08.375 28314-28444 {App Name} D [EDT] 0:0:42,937 - Starting file encryption...
2024-07-28 11:03:08.416 28314-28330 {App ID} I Background young concurrent copying GC freed 10(31KB) AllocSpace objects, 1(8196KB) LOS objects, 0% free, 43MB/43MB, paused 131us total 112.118ms
2024-07-28 11:03:09.839 28314-28330 {App ID} I Background concurrent copying GC freed 1947(87KB) AllocSpace objects, 3(21MB) LOS objects, 36% free, 41MB/65MB, paused 133us total 117.032ms
2024-07-28 11:03:11.031 28314-28444 {App Name} D [EDT] 0:0:45,594 - File encryption DONE
2024-07-28 11:03:11.034 28314-28444 {App Name} D [EDT] 0:0:45,597 - Saving encrypted file...
2024-07-28 11:03:11.177 28314-28330 {App ID} I Background concurrent copying GC freed 18(24KB) AllocSpace objects, 3(28MB) LOS objects, 33% free, 47MB/71MB, paused 231us total 104.218ms
2024-07-28 11:03:12.454 28314-28444 {App Name} D [EDT] 0:0:47,17 - DONE Saving encrypted file