在Android上,在创建一个新的大文件之前和创建时,我怎么知道它会成功而不会耗尽存储空间? 背景
假设我要创建一个大文件(甚至是多个),但我想确保我会成功 问题 我确信要做到这一点,我需要在即将创建或修改的文件上使用或 但是,事实证明,安卓比这更复杂:安卓有缓存文件夹,在需要时可以缩小大小,所以文档说我不应该依赖这些功能(“返回的可用字节数是一个提示,但不是保证”) 再加上不确定哪个更值得信任 因此,即使您从这些函数中获得了一些数字,并且您尝试创建一个比这些函数更大的文件,您可能仍然会成功,因为操作系统将为您清除一些缓存。这是一个很好的方法 我发现了什么 我认为这些可能应该被使用: -这将返回应用程序可以访问的字节 分配并考虑系统愿意删除的缓存。 然后,应用程序可以使用以下方式分配空间: , -这将分配请求的字节 对于应用程序(删除满足 请求) “保证 已分配给打开的文件,否则将抛出[…]” 来自,而“可能受比赛条件的限制。”来自 及 可能有助于获取文件描述符 不确定这到底意味着什么,我还是试着自己去做 给定一个我打算创建一个大文件的文件或文件路径,我想检查我有多少可用空间,知道我是否真的可以在那里创建它,创建它,然后再次检查剩余的空间:在Android上,在创建一个新的大文件之前和创建时,我怎么知道它会成功而不会耗尽存储空间? 背景,android,file,storage,android-8.0-oreo,Android,File,Storage,Android 8.0 Oreo,假设我要创建一个大文件(甚至是多个),但我想确保我会成功 问题 我确信要做到这一点,我需要在即将创建或修改的文件上使用或 但是,事实证明,安卓比这更复杂:安卓有缓存文件夹,在需要时可以缩小大小,所以文档说我不应该依赖这些功能(“返回的可用字节数是一个提示,但不是保证”) 再加上不确定哪个更值得信任 因此,即使您从这些函数中获得了一些数字,并且您尝试创建一个比这些函数更大的文件,您可能仍然会成功,因为操作系统将为您清除一些缓存。这是一个很好的方法 我发现了什么 我认为这些可能应该被使用: -这将返
val storageManager = ContextCompat.getSystemService(this, StorageManager::class.java)!!
val file = File(getExternalFilesDir(null), "largeFile.zip")
file.delete()
val uuidForPath = storageManager.getUuidForPath(file)
val allocatableBytes = storageManager.getAllocatableBytes(uuidForPath)
Log.d("AppLog", "allocatableBytes :${Formatter.formatFileSize(this, allocatableBytes)} - $allocatableBytes bytes")
Log.d("AppLog", "trying to create a new, large file:")
file.parentFile!!.mkdirs()
val fileDescriptor = Os.open(file.absolutePath, 0, 0)
val fileSize: Long = 2L * 1024L * 1024L * 1024L
storageManager.allocateBytes(fileDescriptor, fileSize)
Log.d("AppLog", "file exists?${file.exists()} fileSize:${file.length()}")
val allocatableBytesAfterFileCreated = storageManager.getAllocatableBytes(uuidForPath)
Log.d("AppLog", "allocatableBytes :${Formatter.formatFileSize(this, allocatableBytesAfterFileCreated)} - $allocatableBytesAfterFileCreated bytes")
这向我显示了10.04 GB(10042085376字节)的结果,但这很奇怪,因为在设置应用程序上,它显示了10.57 GB的可用空间
因此,我不确定获得可用空间是否正确,因为这与操作系统所说的有点相去甚远
此外,当应用程序到达创建文件的部分(大小为2GB,应该足以容纳我得到的文件)时,它失败了,出现以下异常:
所以即使直接创建文件,我也不知道怎么做。检查应该创建的文件(使用文件管理器应用程序),我看不到它,所以它确实失败了
我还尝试了allocateBytes的另一个函数,它获取文件的UUID,但得到了相同的异常
不仅如此,所有这些都需要androido(API 26-android8.0)。我以前不知道该怎么办。当然应该有类似的东西,应该足够了
问题
鉴于我失败了,我想问一下如何正确地做到这一点:
1-检查可用空间然后创建文件可能不起作用,因为在检查可用空间和实际创建文件之间,其他应用程序可能会自行创建文件并占用您之前检查过的空间。我建议在
try/catch
block和catch中创建与可用磁盘空间相关的文件,并正确处理它们
4-是的,您可以使用
RandomAccessFile
并使用setLength
方法设置其长度。通过“查询”,我的意思是“检查有多少可用空间可用于创建大文件”。文件.parentFile!!。mkdirs()
根本不是问题所在。它成功了,因为这是应用程序的路径。什么是mkdirp
?它不能存档。请演示如何执行我编写的操作(自由空间查询和创建大文件)。对不起,您是对的,mkdirs
是Java中的mkdirp
。编辑了我的回答我有一个问题,StorageManager.getAllocatableBytes(…)不存在。有人遇到过这个问题吗?@adi9090您是否使用了val-storageManager=ContextCompat.getSystemService(这个,storageManager::class.java)代码>?是,使用相同的方法检索storage manager。项目中的minSdkVersion为23,在24中添加了getAllocateableBytes方法,在增加minSdkVersion后,它再次不可见。我已经完成了清除缓存,但也没有任何帮助,因此我需要找到一个解决方法。@adi9090。那么,也许在这里提出一个新问题。如果您认为这是一个bug,请在问题追踪器上报告:
android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542)
at android.system.Os.open(Os.java:412)