Opening a 12kb text file takes WAY too long…?
-
29-09-2019 - |
Question
The following code works, but takes way too long (over a minute) to open a small file. The LogCat shows a lot of instances of "GC_FOR_MALLOC freed #### objects / ###### bytes in ##ms". Any suggestions?
File dirPath = new File(Environment.getExternalStorageDirectory(), "MyFolder");
String content = getFile("test.txt");
public String getFile(String file){
String content = "";
try {
File dirPathFile = new File(dirPath, file);
FileInputStream fis = new FileInputStream(dirPathFile);
int c;
while((c = fis.read()) != -1) {
content += (char)c;
}
fis.close();
} catch (Exception e) {
getLog("Error (" + e.toString() + ") with: " + file);
}
return content;
}
Update:
This is what it looks like now:
File dirPath = new File(Environment.getExternalStorageDirectory(), "MyFolder");
String content = getFile("test.txt");
public String getFile(String file){
String content = "";
File dirPathFile = new File(dirPath, file);
try {
StringBuilder text = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader(dirPathFile));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
content = new String(text);
} catch (Exception e) {
getLog("Error (" + e.toString() + ") with: " + file);
}
return content;
}
Thank you all!!
Solution
Using +=
on a String is extremely inefficient - it will constantly allocate and deallocate memory, something you need to avoid!
If you need to constantly add characters, use a StringBuilder
and give it a sufficiently big buffer up front.
However, it's even better to just read the entire file as a byte array and then create a string from that byte array. Use the String(byte[])
constructor.
OTHER TIPS
content += (char)c;
Well, here's your problem. String concatenation is slow if you have to do it repeatedly. And you're reading the file one character at a time, which is also really slow.
You want to be using the read(byte[] buffer)
method to read the file into a buffer efficiently. And then you can stringify the buffer if need be.
Rather than reading a single byte at a time, you should read multiple using read(byte[]).
Also, Strings are immutable, so every time you do String s = s + "a"; there is the possibility that you are creating a new String object. You can use StringBuilder instead to build up a larger string.
Schlemiel the painter strikes again!
try to read with buffer read(byte[] buff)
The reasons are:
- You are creating too many String objects with
content += (char)c;
- use StringBuilder instead to append with read data, then in the end call toString() on the StringBuilder. - You don't use a byte[] (or char[], it depends on implementation) buffer to read from file. Usually 1KB buffer is optimal instead of reading one by one byte.