尝试在 phone 内存上写入时出现致命异常:java.lang.OutOfMemoryError
Fatal Exception when trying to write on phone memory: java.lang.OutOfMemoryError
这是完整的例外:
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 79386366 byte allocation with 16777216 free bytes and 75MB until OOM
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:133)
at java.lang.StringBuilder.append(StringBuilder.java:124)
at ch.usi.jacopofidacaro.umob.background.RecordStorageManager.store(RecordStorageManager.java:156)
at ch.usi.jacopofidacaro.umob.recordCommuter.RecordCommuter.storeLocally(RecordCommuter.java:76)
at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder.recordGyroscope(BackgroundRecorder.java:591)
at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder.run(BackgroundRecorder.java:139)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是它发生的地方:
public void store(Record record, String recordId, Context ctx, String recordType) {
Log.i(STORE, "store():");
// convert the POJO to JSON
Gson gson = new Gson();
String json = gson.toJson(record);
String filePath = recordType + "_records";
File file = new File(ctx.getFilesDir(), filePath);
Log.i(STORE, " target file: " + file.getAbsolutePath());
Log.i(STORE, " locally storing record: " + recordId);
try {
if (!file.exists()) file.createNewFile();
FileWriter fw = new FileWriter(file.getAbsolutePath(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(json);
bw.close();
FileReader fr = new FileReader(file.getAbsolutePath());
BufferedReader br = new BufferedReader(fr);
StringBuilder text = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
text.append(line).append('\n');
br.close();
Log.i(STORE, " record stored.");
} catch (Exception e) {
e.printStackTrace();
}
}
简而言之,我正在读取陀螺仪传感器数据并将它们存储在名为 gyroscope_records 的本地文件中。每小时,我都会连接到 Firebase 以上传文件并在下一个小时开始写入新文件。在我看来,如果传感器读数太多并且文件变得非常大,则会发生此异常。但是,我不知道如何处理它。我怎样才能 read/write 大文件(如果这是这里的问题)?
您将不得不以某种方式将文件分解成更小的部分。您目前有一个将近 80MB 的文件,而且听起来它可能会变得更大。你的问题是你试图将整个文件读入内存,但你做不到。
几点建议:
- 创建许多小文件。在这种情况下,我不知道
Record
有多大,但可能每分钟一个新文件或包含较少数量记录的文件。
- 使用SQLite并将每条记录存储在数据库中。定期让另一个线程读出这些记录,发送它们,然后删除它们。
- 仅附加到大文件。不要读入内存。
还有其他的可能性,但您无法将其全部保存在内存中。
我发现 StringBuilder“text
”没有用处,但 text.append(...)
导致了异常。那么您是否尝试过将变量与 while
循环一起删除?
这是完整的例外:
Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 79386366 byte allocation with 16777216 free bytes and 75MB until OOM
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:133)
at java.lang.StringBuilder.append(StringBuilder.java:124)
at ch.usi.jacopofidacaro.umob.background.RecordStorageManager.store(RecordStorageManager.java:156)
at ch.usi.jacopofidacaro.umob.recordCommuter.RecordCommuter.storeLocally(RecordCommuter.java:76)
at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder.recordGyroscope(BackgroundRecorder.java:591)
at ch.usi.jacopofidacaro.umob.background.BackgroundRecorder.run(BackgroundRecorder.java:139)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是它发生的地方:
public void store(Record record, String recordId, Context ctx, String recordType) {
Log.i(STORE, "store():");
// convert the POJO to JSON
Gson gson = new Gson();
String json = gson.toJson(record);
String filePath = recordType + "_records";
File file = new File(ctx.getFilesDir(), filePath);
Log.i(STORE, " target file: " + file.getAbsolutePath());
Log.i(STORE, " locally storing record: " + recordId);
try {
if (!file.exists()) file.createNewFile();
FileWriter fw = new FileWriter(file.getAbsolutePath(), true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(json);
bw.close();
FileReader fr = new FileReader(file.getAbsolutePath());
BufferedReader br = new BufferedReader(fr);
StringBuilder text = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
text.append(line).append('\n');
br.close();
Log.i(STORE, " record stored.");
} catch (Exception e) {
e.printStackTrace();
}
}
简而言之,我正在读取陀螺仪传感器数据并将它们存储在名为 gyroscope_records 的本地文件中。每小时,我都会连接到 Firebase 以上传文件并在下一个小时开始写入新文件。在我看来,如果传感器读数太多并且文件变得非常大,则会发生此异常。但是,我不知道如何处理它。我怎样才能 read/write 大文件(如果这是这里的问题)?
您将不得不以某种方式将文件分解成更小的部分。您目前有一个将近 80MB 的文件,而且听起来它可能会变得更大。你的问题是你试图将整个文件读入内存,但你做不到。
几点建议:
- 创建许多小文件。在这种情况下,我不知道
Record
有多大,但可能每分钟一个新文件或包含较少数量记录的文件。 - 使用SQLite并将每条记录存储在数据库中。定期让另一个线程读出这些记录,发送它们,然后删除它们。
- 仅附加到大文件。不要读入内存。
还有其他的可能性,但您无法将其全部保存在内存中。
我发现 StringBuilder“text
”没有用处,但 text.append(...)
导致了异常。那么您是否尝试过将变量与 while
循环一起删除?