获取 Android 文件资源的大小?

25

我有一个视频文件在资源的raw文件夹中。 我想查找该文件的大小。 我有这段代码:

Uri filePath = Uri.parse("android.resource://com.android.FileTransfer/" + R.raw.video);
                File videoFile = new File(filePath.getPath());
                Log.v("LOG", "FILE SIZE "+videoFile.length());

但它总是给我一个大小为0的值。我做错了什么?

5个回答

24

试试下面这几行代码:

InputStream ins = context.getResources().openRawResource (R.raw.video)
int videoSize = ins.available();

和我刚才在 @EboMike 的回答下发表的问题/评论一样。这种方式从未出现过任何问题吗? - psycho
3
openRawResource() 返回的不是普通的 InputStream,而是 AssetInputStream。这个子类覆盖了 available() 方法,并且能够提供可靠的信息。 - caw
@MarcoW。根据文档,似乎不是这样的:http://developer.android.com/reference/android/content/res/AssetManager.AssetInputStream.html#available() - CodeClown42
1
@goldilocks:好的,是的!如果你查看 InputStream.available() 的文档,你会发现这就是解释来源。AssetInputStream 在 JavaDoc 中使用了完全相同的文本:http://developer.android.com/reference/java/io/InputStream.html#available() 但是源代码显示 AssetInputStream.available() 覆盖了超类的方法并从一个本地方法获取其结果:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/content/res/AssetManager.java#AssetManager.AssetInputStream.available%28%29 - caw
@MarcoW。我不怀疑这一点,也不怀疑它在某些实现中(包括当前的Android)可以工作。但是,如果您的标准是API实际承诺的内容,那么API并没有承诺这一点。如果明天在某些设备上无法正常工作,那么你就会因为相信一些基本的编程原则而受到责备!此外,还有一种安全、按照规范的方法——请参见shem的答案。在我看来,这是最佳的方法。 - CodeClown42

24

试一下这个:

AssetFileDescriptor sampleFD = getResources().openRawResourceFd(R.raw.video);
long size = sampleFD.getLength()

5
这看起来比其他答案更安全。 - Snicolas
3
+1 但是在许多文件类型上默认不起作用,因为aapt对它们进行了压缩——解决办法请参见这里:http://stackoverflow.com/questions/19743169/how-can-i-use-openrawresourcesfd/19743170 - CodeClown42

16

你无法使用 File 来获取资源。请使用 Resources 或者 AssetManager 来获得一个指向该资源的 InputStream,之后调用 available() 方法。

就像这样:

InputStream is = context.getResources().openRawResource(R.raw.nameOfFile);
int sizeOfInputStram = is.available(); // Get the size of the stream

14
这个有没有问题?这种方法应该返回“可以读取的估计字节数”,并不一定是真实的文件大小,而且文档明确反对使用它... http://developer.android.com/reference/java/io/InputStream.html#available() - psycho
6
文档提到了可能需要一段时间才能检索数据的通用流,比如网络流。在资源中,确切的大小总是已知并可用的。 - EboMike

10

@shem答案进行了轻微修改

AssetFileDescriptor afd = contentResolver.openAssetFileDescriptor(fileUri,"r");
long fileSize = afd.getLength();
afd.close();

其中fileUri是Android Uri类型。


2

可重用的Kotlin扩展函数

您可以在上下文或活动中调用它们。它们具有异常安全性。

fun Context.assetSize(resourceId: Int): Long =
    try {
        resources.openRawResourceFd(resourceId).length
    } catch (e: Resources.NotFoundException) {
        0
    }

这个不如第一个好,但在某些情况下可能是必需的。

fun Context.assetSize(resourceUri: Uri): Long {
    try {
        val descriptor = contentResolver.openAssetFileDescriptor(resourceUri, "r")
        val size = descriptor?.length ?: return 0
        descriptor.close()
        return size
    } catch (e: Resources.NotFoundException) {
        return 0
    }
}

如果您想要一种简单的方式来获取不同的字节表示,您可以使用以下方法。
val Long.asKb get() = this.toFloat() / 1024
val Long.asMb get() = asKb / 1024
val Long.asGb get() = asMb / 1024 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接