繁体   English   中英

调用 FileInfo.Length 时出现 UnauthorizedAccessException

[英]UnauthorizedAccessException when calling FileInfo.Length

我确实通过 Crashlytics 收到报告,当我调用FileInfo.Length;时,我的 Unity 应用程序的某些用户(大约 0.5%)收到 UnauthorizedAccessException FileInfo.Length;

堆栈跟踪的有趣部分是:

Non-fatal Exception: java.lang.Exception
UnauthorizedAccessException : Access to the path '/storage/emulated/0/Android/data/com.myCompany.myGreatGame/files/assets/myAsset.asset' is denied.
System.IO.__Error.WinIOError (System.IO.__Error)
System.IO.FileInfo.get_Length (System.IO.FileInfo)

相应的文件(对于每个报告来说都是不同的文件)是由同一个应用程序(可能是之前的多个会话)编写的(或当前正在编写的)。 调用发生在后台线程中,并且可能同时进行一些写入。 但是根据 .net doc 这个属性应该是预先缓存的(见https://docs.microsoft.com/en-us/dotnet/api/system.io.fileinfo.length?view=netframework-2.0

导致它的整个代码是:

private static long DirSize(DirectoryInfo d) 
{
    long size = 0;
    FileInfo[] fileInfos = d.GetFiles();
    foreach (FileInfo fileInfo in fileInfos) 
    {      
        size += fileInfo.Length;
    }
    ...

有没有人经历过类似的事情并知道可能是什么原因造成的?

这看起来是一个非常奇特的错误,因此,我没有证据支持我的建议。

建议1:
用户已安装防病毒软件 - 这些应用程序有时像恶意软件一样工作,锁定主机程序未使用的文件来测试它们(特别是如果它们想防止恶意行为)。 这将解释错误的罕见性质。 在 Length 方法调用失败后,我会尝试查看文件的权限,这可能会给您(也可能是我们)更多的见解。

建议2:
在某些情况下,当应用程序主动写入此文件时,您无法读取长度。 这不应该发生,但即使在操作系统中也会发生错误。 可能的路径:某些应用程序正在写入文件。 文件被修改并写入元数据(包括长度),而碰巧您正在从另一个线程读取长度,操作系统锁定文件以防止读取元数据(包括长度),同时写入元数据(可能是出于安全原因)

建议 3(也是最有可能的):
坏 SD 卡/内存/CPU - 由于您无法控制客户端的硬件,因此总会发生一些随机错误。 我会检查这 0.5% 的错误是否不是来自一个用户,或者似乎来自多个用户,但由于硬件的其他问题,他们的唯一 ID 重置(检查其他数据,如手机型号,因为这也可能为您提供线索)。

您很可能正在尝试访问您无权访问的文件。 有些文件即使是管理员也无法访问。

您可以执行 Try/Catch 块来处理异常。

看到这个问题

如果您仔细阅读Microsoft 的文档,它会明确指出:

  1. 如果刷新失败,则会引发 I/O 错误
  2. FileInfo.Length 属性仅在非常精确的案例列表(GetDirectories、GetFiles、GetFileSystemInfos、EnumerateDirectories、EnumerateFiles、EnumerateFileSystemInfos)中预缓存。 应通过调用 Refresh() 方法刷新缓存的信息。

插入 #1 和 #2 可以轻松识别问题:当您尝试获取该信息时,您打开了一个带有排他锁的文件,这会给您带来 #1 中的错误。 我建议实现两种不同的逻辑,一种是明显的 try/catch 块,但是因为该块 (a) 性能成本和 (b) 不能解决知道文件大小的逻辑问题,您还应该缓存当您获得排他锁时,您可以自己处理这些数据。

将它们放在内存中的静态表中,一个简单的键/值(文件/大小),并在调用 FileInfo.Length() 之前对其进行检查。 基本上,当您获得锁时,您将文件/大小值添加到字典中,完成后将其删除。 这样,您将永远不会再次出现错误,同时能够计算目录大小。

~皮诺

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM