Android SAF写入文件残留原文件尾部内容问题如何解决
问题诱因
- Android 11开始,存储访问框架(SAF)的
openOutputStream(uri)默认行为发生变更:旧版本系统(如你使用的Android 8.1)默认写入时会自动截断原文件,而新版本系统默认仅覆盖写入对应长度的内容,不会主动清除原文件超出新内容长度的尾部数据,因此新文件体积小于原文件时就会残留旧代码。 - 你现有的长度校验逻辑仅校验了写入字节数和源数据长度的一致性,只能确认你预期的内容全部写入成功,无法感知原文件尾部的残留内容,因此不会触发异常。
修复方案
方案1:显式指定截断模式写入(推荐)
调用openOutputStream时显式传入模式参数"rwt",强制开启写入前截断原文件的逻辑,该模式从Android 8.0(API 26)开始支持:
OutputStream os = getContentResolver().openOutputStream(uri, "rwt")
如果你的应用需要兼容低于API 26的系统,可增加版本判断:
OutputStream os; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { os = getContentResolver().openOutputStream(uri, "rwt"); } else { os = getContentResolver().openOutputStream(uri); }
参数说明:
r:申请读权限(可选,搭配写入场景更稳妥)w:申请写权限t:开启截断模式,写入前清空原文件全部内容
方案2:写入完成后手动截断文件(兜底方案)
写入完成后调用DocumentsContract.truncate()方法,手动将文件长度截断为实际写入的字节数,可彻底避免残留问题:
// 写入完成、flush之后增加以下逻辑 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { DocumentsContract.truncate(getContentResolver(), uri, lengthTotal); }
内容的提问来源于stack exchange,提问作者donmor3000
相关产品推荐
相关产品推荐

