Android API31下Kotlin写入ByteArray到U盘文件为空问题求助
问题分析与解决方案
核心问题定位
- 写入逻辑分支错误:原代码中将写入操作包裹在
if (!myDir.exists())分支内,仅当目录首次创建时才执行写入,后续运行因目录已存在直接跳过写入步骤,导致文件为空。 - 外接存储缓存未同步:Android对外接U盘的写入存在缓存机制,若未强制同步,数据可能仅停留在内存缓存中,未实际写入物理介质。
- 异常捕获不完整:原代码仅捕获了目录创建的异常,写入过程的潜在错误未被捕获,无法排查隐式问题。
修复代码示例
fun writeToUsb(storageVolume: StorageVolume) { when(storageVolume.state) { Environment.MEDIA_MOUNTED -> { val rootDir = storageVolume.directory ?: return // 判空避免空指针异常 val myDir = File(rootDir, "errors") // 确保目录存在,mkdirs()在目录已存在时返回false但不报错 if (!myDir.exists() && !myDir.mkdirs()) { Log.e("DirError", "创建目录失败: ${myDir.path}") return } val dataToWrite = "FooBar".toByteArray() val file = File(myDir, "errorlog.txt") // 使用try-with-resources自动管理流资源,避免泄漏 runCatching { FileOutputStream(file).use { fos -> fos.write(dataToWrite) fos.flush() file.fsync() // 强制同步缓存到物理U盘(API 26+支持,符合API31要求) } Log.i("WriteSuccess", "数据写入成功: ${file.path}") }.onFailure { e -> Log.e("WriteError", "写入文件失败", e) // 打印完整异常栈信息 } } } }
关键修复点说明
- 调整写入逻辑:将写入操作移出目录判断分支,确保无论目录是否已存在,都执行写入流程。
- 强制缓存同步:调用
file.fsync()强制将内存缓存中的数据刷新到物理U盘,解决内容写入后不显示的问题。 - 完善异常处理:通过
runCatching捕获所有写入相关异常,并打印完整栈信息,快速定位潜在问题。 - 增加空指针防护:对
storageVolume.directory进行判空,避免因存储卷信息异常导致崩溃。
额外注意事项
- 避免无意义的文件删除-重建操作(如补充测试中的代码逻辑),这种操作会导致文件状态混乱,增加写入失败概率。
- 确认传入的
storageVolume为正确的外接U盘实例,可通过打印storageVolume.directory?.path验证路径是否指向U盘根目录。
内容的提问来源于stack exchange,提问作者snux_cs
相关产品推荐
相关产品推荐

