【发布时间】:2014-02-10 07:27:03
【问题描述】:
在我的应用程序中,我在一天结束时将一些数据同步到应用程序服务器。为此,我将所有数据包装为 JSONObjects 的 JSONArray。数据主要包括大约 50 张图片,每张图片大小约为 50kb(以及一些文本数据)。所有这些图片都使用base64编码进行编码。当上传的图片(以及一些文本数据)数量很少时一切正常,但是当我上传大量图片时,比如大约50张,然后我看到所有数据都正确形成JSONArray的日志,但是当我尝试使用'array.toString()'方法显示JSONArray时遇到内存不足异常。我相信这是由于堆已满(但是,当我尝试在清单中制作 android:largeHeap="true" 时,一切正常,但是我想避免使用这种方法,因为这不是一个好习惯)。我的意图只是将此 JSONArray 值写入文件然后将此文件分成小块并将其发送到服务器。 请指导我将 JSONAray 值写入不会导致 OOM 问题的文件的最佳方法。谢谢!
以下是 JSONArray 的格式:
[{"pid":"000027058451111","popup_time":"2014-01-13 23:36:01","picture":"...base64encoded string......","punching_time":"Absent","status":"Absent"},{"pid":"000027058451111","popup_time":"2014-01-13 23:36:21","picture":"...base64encoded string......","punching_time":"Absent","status":"Absent"}]
以下是我的代码的主要 sn-ps:
JSONObject aux;
JSONArray array = new JSONArray();
.
.
// Looping through each record in the cursor
for (int i = 0; i < count; i++) {
aux = new JSONObject();
try {
aux.put("pid", c.getString(c.getColumnIndex("pid")));
aux.put("status", c.getString(c.getColumnIndex("status")));
aux.put("pop_time", c.getString(c.getColumnIndex("pop_time")));
aux.put("punching_time", c.getString(c.getColumnIndex("punching_time")));
aux.put("picture", c.getString(c.getColumnIndex("image_str"))); // stores base64encoded picture
} catch (Exception e) {
e.printStackTrace();
}
array.put(aux); // Inserting individual objects into the array , works perfectly fine,no error here
c.moveToNext(); // Moving the cursor to the next record
}
Log.d("Log", "length of json array - "+array.length()); // shows me the total no of JSONObjects in the JSONArray,works fine no error
// HAD GOT OOM HERE
//Log.d("Log", "JSONArray is - " + array.toString());
if (array.length() != 0){
try {
String responseCode = writeToFile(array); //Writing the JSONArray value to file,which will then send file to server.
if(responseCode.equals("200"))
Log.d("Log","Data sent successfully from app to app server");
else
Log.d("Log","Data NOT sent successfully from app to app server");
} catch (Exception e) {
e.printStackTrace();
}
}
.
.
private String writeToFile(JSONArray data) {
Log.d("Log", "Inside writeToFile");
File externalStorageDir = new File(Environment.getExternalStorageDirectory().getPath(), "Pictures/File");
if (!externalStorageDir.exists()) {
externalStorageDir.mkdirs();
}
String responseCode = "";
File dataFile = new File(externalStorageDir, "File");
/* FileWriter writer;
String responseCode = "";
try {
writer = new FileWriter(dataFile);
writer.append(data);
writer.flush();
writer.close();
responseCode = sendFileToServer(dataFile.getPath(), AppConstants.url_app_server); // Sends the file to server,worked fine for few pictures
} catch (IOException e) {
e.printStackTrace();
}*/
try {
FileWriter file = new FileWriter("storage/sdcard0/Pictures/File/File");
file.write(data.toString()); // GOT OOM here.
file.flush();
file.close();
Log.d("Log","data written from JSONArray to file");
responseCode = sendFileToServer(dataFile.getPath(), AppConstants.url_app_server); // Sends the file to server,worked fine for few pictures
} catch (IOException e) {
e.printStackTrace();
}
return responseCode;
}
public String sendFileToServer(String filename, String targetUrl) {
.
.
// Sends the file to server,worked fine for few pictures
.
.
return response;
}
【问题讨论】:
-
你的 JSON 中有这个:"picture":"...base64encoded string......" ...我要疯了猜猜然后说……你的内存快用完了,因为你吸入的图片比你的内存要多。
-
既然问题是传入了很多图片,你为什么不把一个大的同步过程分成更易于管理的块(比如五个请求,每个请求 10 张图片,或者你想要的) ) - 将 json 构造为不超过 10 个(左右)条目。
-
@sunil :这就是我试图对文件执行的操作。我将 JSONArray 值存储在文件中,然后我目前正在将此文件的小块发送到我的服务器(这段代码有效很好)。但是在将文件发送到服务器的过程之前(对于 50 张图片的情况),我在尝试将 JSONArray 值写入文件时遇到了 OOM:/
-
@BrianRoach:是的,我将图片编码为 base64 编码字符串(这对于每张图片来说都是一个非常大的编码字符串)。你是对的,我的内存不足(但是当我在清单中将堆设置为“大”,一切正常,但正如我所说,我不想使用这种方法)。我只需要将 JSONArray 中的值(工作正常)存储到文件中。是有没有办法做到这一点?
标签: java android string out-of-memory arrays