I have a performance problem with String Handling.
I have a log file (simple text file) that I have to manipulate and performa several changes in text.
So the program adds line by line in one huge String.
Basically it do.
while (not_finished) {
// create new stringAdd;
stringResult=stringResult + stringAdd + "\n";
}
// output to a textArea in window
textArea.setText(stringResult);
Now the performances for this is horrible, so I upgraded to StringBuilder
StringBuilder result= new StringBuilder();
while (not_finished) {
// create new stringAdd;
result.append( stringAdd +"\n");
}
// output to a textArea in window
textArea.setText(result.toString());
This is much faster. String once added to result will not be changed. The problem is not with the performances when there are more than 400,000 lines (one line has from 1 to 70 characters).
How to increase performances of building String? Do you have any idea?
2 Answers 2
Two things can be improved. You are still concatenating strings inside the loop, so you can try:
result.append(stringAdd).append('\n');
If you know the size of the string beforehand, you can minimize the number of internal buffer resizing:
// expecting 30k characters:
StringBuilder result= new StringBuilder(30_000);
3 Comments
To just read a text file, there is absolutely no need to parse the file line by line in the first place. The right tool for the reading part is InputStreamReader, that will provide the translation from file encoding to characters. To Speed up the actual file reading to reasonable performance, put a BufferedInputStream in between the actual FileInputStream and the InputStreamReader.
So to set up the file for reading, in principle you nest three sources like this:
InputStream is = new FileInputStream(...);
InputStream bi = new BufferedInputStream(is);
InputStreamReader reader = new InputStreamReader(bi, (CharSet));
The actual reading is then a simple loop, without any fancy logic:
StringBuilder buffer = new StringBuilder();
// possible optimization would be: new StringBuilder((int) file.length());
int c = reader.read();
while (c >= 0) {
buffer.append((char) c);
c = reader.read();
}
(Error handling and resource management omitted, in reality this will need try/catch to deal with the possible exceptions)
Since the text file is already containing line feeds (naturally) there is no reason to break it into lines and then put the lines back together.
At the end just do one simple toString() for the buffer and there's your String:
String contents = buffer.toString();
This method will not create any intermediate objects per read (StringBuilder adjusting its capacity aside). Its complexity is basically O(N), meaning time needed will increase only linearly with file size.
BufferedReader? Is it buffer size large enough?