簡體   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