Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android上,在创建一个新的大文件之前和创建时,我怎么知道它会成功而不会耗尽存储空间? 背景_Android_File_Storage_Android 8.0 Oreo - Fatal编程技术网

在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)。我以前不知道该怎么办。当然应该有类似的东西,应该足够了

问题 鉴于我失败了,我想问一下如何正确地做到这一点:

  • 如何查询可以在给定文件路径上创建的文件的实际最大大小?或者,如果我打算创建多个文件,在我真正创建它们之前就知道它们是可以创建的

  • 即使在创建文件时,我如何立即分配它们(无需查询),以确保我确实成功了

  • 当运行在旧的Android版本(Android 8.0之前)上时,解决这个问题的最佳方法是什么

  • 还有其他的选择吗?我想我以前听说过(在C/C++课程中)有一个技巧,可以通过将文件中的“光标”移动到写入文件的最远位置来创建一个大文件。也许它也是Java/Kotlin上的一个可能的替代方案,在Android上?也许使用随机存取文件


  • 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)