我在将ArrayLists存储和检索到设备的内部存储时遇到了一些麻烦。我有一个自定义的序列化器/反序列化器,我已成功使用它来存储和检索SharedPreferences中的数据。但是,我无法使用存储在设备内部存储中的文件。我需要做出这一步,因为我的日期对于SharedPreferences而言变得太大了。
我非常感谢这个问题的一些帮助。我的代码可能有一个明显的问题,因为我对此很新,并且从未尝试过存储和从Android内部存储中检索(尝试将其作为业余爱好)。任何帮助将不胜感激......
有明显的问题吗?有没有更好的方法呢?
serialiser / deserialiser是这样的:
package com.ctech.dailybread.io;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectSerializer {
private static final Log log = LogFactory.getLog(ObjectSerializer.class);
public static String serialize(Serializable obj) throws IOException {
if (obj == null) return "";
ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
objStream.writeObject(obj);
objStream.close();
return encodeBytes(serialObj.toByteArray());
}
public static Object deserialize(String str) throws IOException, ClassNotFoundException {
if (str == null || str.length() == 0) return null;
ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str));
ObjectInputStream objStream = new ObjectInputStream(serialObj);
return objStream.readObject();
}
public static String encodeBytes(byte[] bytes) {
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
}
return strBuf.toString();
}
public static byte[] decodeBytes(String str) {
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length(); i+=2) {
char c = str.charAt(i);
bytes[i/2] = (byte) ((c - 'a') << 4);
c = str.charAt(i+1);
bytes[i/2] += (c - 'a');
}
return bytes;
}
}
我使用的存储方法是:
public static void storeToFile(Context ctx, String fileName, ArrayList input) {
String fileName2 = fileName + ".ser";
try (
OutputStream os = ctx.openFileOutput(fileName2, Context.MODE_PRIVATE);
OutputStream buffer = new BufferedOutputStream(os);
ObjectOutput output = new ObjectOutputStream(buffer);
){
output.writeChars(ObjectSerializer.serialize(input));
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
}
在加载文件时,在这种情况下,列出了一天的日期&#39;对象:
public static ArrayList<Day> loadDayListFromFile(Context ctx) {
InputStream is = null;
try {
is = ctx.openFileInput("dayList.ser");
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF8"));
dayList = (ArrayList<Day>) ObjectSerializer.deserialize(reader.toString());
} catch (IOException | ClassNotFoundException e) {
Toaster.toastItShort("Unable to load day list", ctx);
e.printStackTrace();
}
} catch (FileNotFoundException e) {
Toaster.toastItShort("Could not find day list file", ctx);
e.printStackTrace();
}
return dayList;
}
当加载文件时,此时包含并清空ArrayList会抛出致命的ArrayIndexOutOfBounds错误:
02-11 13:24:43.460 18966-18966 / com.ctech.dailybread E / AndroidRuntime:FATAL EXCEPTION:main 过程:com.ctech.dailybread,PID:18966 java.lang.RuntimeException:无法启动活动ComponentInfo {com.ctech.dailybread / com.ctech.dailybread.activities.ProgressDetail}:java.lang.ArrayIndexOutOfBoundsException:length = 15;指数= 15 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 在android.app.ActivityThread.access $ 800(ActivityThread.java:144) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1278) 在android.os.Handler.dispatchMessage(Handler.java:102) 在android.os.Looper.loop(Looper.java:135) 在android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) 在java.lang.reflect.Method.invoke(Method.java:372) 在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:899) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 引起:java.lang.ArrayIndexOutOfBoundsException:length = 15;指数= 15 在com.ctech.dailybread.io.ObjectSerializer.decodeBytes(ObjectSerializer.java:66)...
...在对象序列化器中引用此行...
bytes[i/2] = (byte) ((c - 'a') << 4);