You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓Marshmallow设备中SharedPreferences存储的字符串重启APP后被修改?

解决Marshmallow设备上SharedPreferences存储字符串换行符异常的问题

哇,这个问题确实挺磨人的,尤其是只在单台Marshmallow设备上出现,排查24小时肯定费了不少精力!我来帮你梳理下思路和解决方案:

问题本质

你遇到的核心问题是Android 6.0(Marshmallow)的SharedPreferences在持久化字符串时,自动将CR LF(\r\n)转换成了LF(\n),重启APP读取后,字符串的字节结构发生了变化,导致和原服务器返回的字符串equals()不匹配。至于在线对比工具显示相同,是因为多数工具会自动归一化换行符格式,忽略CR的存在,所以肉眼看起来一致,但底层字节是不同的。

可行的解决方案

这里给你几个具体的解决办法,按推荐程度排序:

  • Base64编码存储(最稳妥)
    把要存储的字符串先转成Base64编码,这样所有控制字符都会被转换成普通字符,完全避免系统对字符串的修改。示例代码:

    // 存储时
    String originalStr = "你的服务器返回字符串";
    String encodedStr = Base64.encodeToString(originalStr.getBytes(), Base64.DEFAULT);
    sharedPreferences.edit().putString("key", encodedStr).apply();
    
    // 读取时
    String encodedStr = sharedPreferences.getString("key", "");
    String restoredStr = new String(Base64.decode(encodedStr, Base64.DEFAULT));
    

    这种方法能彻底解决任何字符编码或控制字符的存储问题,适合对字符串完整性要求高的场景。

  • 统一换行符格式
    在存储前手动将所有CR LF替换成LF,或者反过来,确保存储和读取时的换行符格式一致。比如:

    // 存储前统一换行符为LF
    String normalizedStr = originalStr.replace("\r\n", "\n");
    sharedPreferences.edit().putString("key", normalizedStr).apply();
    
    // 如果需要和服务器返回的字符串对比,读取后再转回去(或者服务器端也统一格式)
    String restoredStr = sharedPreferences.getString("key", "").replace("\n", "\r\n");
    

    这个方法简单直接,但需要确保服务器返回的字符串格式是固定的,或者你能控制对比时的格式统一。

  • 改用内部文件存储
    如果SharedPreferences的这个行为实在无法规避,可以考虑用Android的内部文件存储来保存字符串,直接写入字节流,完全由自己控制存储内容:

    // 存储到内部文件
    try (FileOutputStream fos = context.openFileOutput("my_string.txt", Context.MODE_PRIVATE)) {
        fos.write(originalStr.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    // 读取文件
    try (FileInputStream fis = context.openFileInput("my_string.txt")) {
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        String restoredStr = new String(buffer);
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    这种方式完全绕过SharedPreferences的处理逻辑,能保证字符串的原始字节不被修改。

补充说明

Marshmallow的SharedPreferences实现和后续Android版本有一些差异,可能是当时的底层存储逻辑对字符串做了自动换行符归一化处理,而后续版本修复了这个行为,所以只在这台设备上出现问题。用Base64编码是最通用的解决方案,几乎不会有兼容性问题。

内容的提问来源于stack exchange,提问作者Hanzyusuf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:17:24