问题
I am trying to convert a large stream (4mb) to a string which i eventually convert it to a JSON Array.
when the stream size is small ( in KB ) every thing works fine, the minute it starts to process the 4mb stream it runs out of memory
below is what i use use to convert the stream to string, I've tried almost every thing and i suspect the issue is with the while loop. can some one please help?
public String convertStreamToString(InputStream is)
throws IOException {
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try
{
Reader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1)
{
writer.write(buffer, 0, n);
}
}
finally
{
is.close();
}
return writer.toString();
} else {
return "";
}
}
Update: ok this is where i reached at the moment, am i on the right track? I think i am close.. not sure what else i can close or flush to regain memory..
public String convertStreamToString(InputStream is)
throws IOException {
String encoding = "UTF-8";
int maxlines = 2000;
StringWriter sWriter = new StringWriter(7168);
BufferedWriter writer = new BufferedWriter(sWriter);
BufferedReader reader = null;
if (is == null) {
return "";
} else {
try {
int count = 0;
reader = new BufferedReader(new InputStreamReader(is, encoding));
for (String line; (line = reader.readLine()) != null;) {
if (count++ % maxlines == 0) {
sWriter.close();
// not sure what else to close or flush here to regain memory
//Log.v("Max Lines Reached", "Max Lines Reached");;
}
writer.write(line);
}
Log.v("Finished Loop", "Looping over");
} finally {
is.close();
writer.close();
}
return writer.toString();
}
}
回答1:
StringWriter
writes to a StringBuffer
internally. A StringBuffer
is basically a wrapper round a char
array. That array has a certain capacity. When that capacity is insufficient, StringBuffer
will allocate a new larger char
array and copy the contents of the previous one. At the end you call toString()
on the StringWriter, which will again copy the contents of the char
array into the char
array of the resulting String.
If you have any means of knowing beforehand what the needed capacity is, you should use StringWriter's contructor that sets the initial capacity. That would avoid needlessly copying arrays to increase the buffer.
Yet that doesn't avoid the final copy that happens in toString()
. If you're dealing with streams that can be large, you may need to reconsider whether you really need that inputstream as a String
. Using a sufficiently large char
array directly would avoid all the copying around, and would greatly reduce memory usage.
The ultimate solution would be to do some of the processing of the input, before all of the input has come in, so the characters that have been processed can be discarded. This way you'll only need to hold as much in memory as what is needed for a processing step.
来源:https://stackoverflow.com/questions/14004933/out-of-memory-when-converting-a-large-stream-to-string