使用 SharedPreferences 保存字节数组

Posted

技术标签:

【中文标题】使用 SharedPreferences 保存字节数组【英文标题】:Saving byte array using SharedPreferences 【发布时间】:2013-11-02 14:23:36 【问题描述】:

所以我有一个 byte [] array 我在我的 android 应用程序中创建的。我想使用来自 android 的 SharedPreferences 来存储它并在我启动我的应用程序时再次检索它。 我怎样才能做到这一点 ?

【问题讨论】:

你有没有尝试过? 【参考方案1】:

你可以尝试保存它有一个String:

存储数组:

SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("myByteArray", Arrays.toString(array));

检索数组:

SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
String stringArray = settings.getString("myByteArray", null);

if (stringArray != null) 
    String[] split = stringArray.substring(1, stringArray.length()-1).split(", ");
    byte[] array = new byte[split.length];
    for (int i = 0; i < split.length; i++) 
      array[i] = Byte.parseByte(split[i]);
    

【讨论】:

不工作。还有你为什么要做'String[] split = stringArray.substring(1, stringArray.length()-1).split(", ");' ? 您能否详细说明为什么它不起作用?代码在我这边测试得很好。至于子字符串,它已经完成,因为当您调用Arrays.toString(array) 时,它会创建一个“[1, 2, 3, 4]”形式的String。所以substring() 是删除方括号,split() 是获取一个包含各个数字的字符串数组,这样我们就可以轻松地将它们解析为字节。 当我保存图像的字节 [] 并且一段时间后我想从 sharedPreferences 中检索它时,它会根据图像大小冻结应用程序 5-15 或 20 秒。如果是大图像,则需要 25-30 秒))所以我认为最好的方法是将其保存在文件中) SharedPreferences 不适用于大量数据,它由文件系统上的简单 xml 文件支持。另外,如果您的应用程序卡住了,可能是因为您在主 UI 线程中运行该操作?【参考方案2】:

我无法投票赞成 Ariel Yust 的回答,但效果很好。

其他答案(如 Base64 编码器)不适用于我的最低 API 版本或未保留原始值(加密/解密数据时可能会出现问题)

作为补充,我建议在 kotlin 中使用扩展:

val String.toPreservedByteArray: ByteArray
get() 
    return this.toByteArray(Charsets.ISO_8859_1)


val ByteArray.toPreservedString: String
get() 
    return String(this, Charsets.ISO_8859_1)

然后你只需在你的字符串上调用它:

val string = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE).getString("string", "") ?: ""
val byteArray = string.toPreservedByteArray

【讨论】:

谢谢,我很高兴它也适用于 Kotlin。【参考方案3】:

当您将其转换为 Base64 字符串时,您实际上是 enlarge the size of a data。

Base64 编码二进制数据的最终大小等于原始数据大小的 1.37 倍 + 814 字节(对于标头)。

使用Charsets.ISO_8859_1在 SharedPreferences 中保存一个字节[] 更快,内存效率更高

private static final String PREF_NAME = "SharedPreferences_Name";
private static final String DATA_NAME = "BytesData_Name";

public static byte[] getBytes(Context ctx) 
    SharedPreferences prefs = ctx.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
    String str = prefs.getString(DATA_NAME, null);
    if (str != null) 
        return str.getBytes(Charsets.ISO_8859_1);
    
    return null;


public static void setBytes(Context ctx, byte[] bytes) 
    SharedPreferences prefs = ctx.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
    SharedPreferences.Editor e = prefs.edit();
    e.putString(DATA_NAME, new String(bytes, Charsets.ISO_8859_1));
    e.commit();

ISO_8859_1 保留您的数据(与 UTF-8 和 UTF-16 不同) 如果您要在应用程序外部传输这些字节,例如使用 JSON,那么您必须在序列化它们之前将 byte[] 转换为 Base64。 JSON 将无法理解 ISO_8859_1 将使用的奇怪字符。

提示:如果您想节省更多空间(以防您节省大量字节 []),请在将字节 [] 转换为任何格式(ISO 或 Base64)

【讨论】:

如果你的数组很大,你不应该使用SharedPreferences。来自Saving Key-Value Sets:“如果您想要保存相对较小的键值集合,您应该使用 SharedPreferences API。” ISO_8859_1 在 Android 中是 8 位干净的行为是否记录在任何地方? @EdwardBrey 我已经包含了一个关于它的链接,并为一家医疗公司实现了适用于 Android 和 ios 组合的代码 - 测试并有效 - 自己尝试一下 :)【参考方案4】:

您可以使用 android.util.Base64 在 SharedPreferences 中保存一个字节数组。

为了节省:

String saveThis = Base64.encodeToString(array, Base64.DEFAULT);

用于加载:

byte[] array = Base64.decode(stringFromSharedPrefs, Base64.DEFAULT);

【讨论】:

很好的复制和过去解决方案,但是我使用 Base64.NO_WRAP 而不是 Base64.DEFAULT 恕我直言,没有理由在首选项中使用换行符。【参考方案5】:

在共享首选项中保存数组:

public static boolean saveArray()

    SharedPreferences sp = SharedPreferences.getDefaultSharedPreferences(this);
    SharedPreferences.Editor mEdit1 = sp.edit();
    mEdit1.putInt("Status_size", byteArr.size()); /* byteArr is an array */ 

    for(int i=0;i<byteArr.size();i++)  
    
        mEdit1.remove("Status_" + i);
        mEdit1.putString("Status_" + i, byteArr.get(i));  
    

    return mEdit1.commit();     

从共享首选项加载数组数据:

public static void loadArray(Context mContext)
  
    Shared Preferences mSharedPreference1 = PreferenceManager.getDefaultSharedPreferences(mContext);
    byteArr.clear();
    int size = mSharedPreference1.getInt("Status_size", 0);  

    for(int i=0;i<size;i++) 
    
        byteArr.add(mSharedPreference1.getString("Status_" + i, null));
    

实现并调用上述2个函数。我希望上面的代码有帮助

【讨论】:

以上是关于使用 SharedPreferences 保存字节数组的主要内容,如果未能解决你的问题,请参考以下文章

使用SharedPreferences保存图片与对象

使用SharedPreferences保存图片与对象

使用 SharedPreferences 保存字符串

使用 SharedPreferences 在 ListView 中保存 ToggleButton 状态

使用 sharedpreferences 保存一个 int 变量“highscore”[重复]

从SharedPreferences保存并检索Intent