Windows 對檔案路徑有 256 個字符的限制,但用戶絕對可以創建路徑長度超過 256 個字符的檔案。讓我們將小于或等于 255 個字符的檔案路徑稱為短路徑,將大于或等于 256 個字符的檔案路徑稱為長路徑。
在處理另一個問題時,我需要檢查給定檔案路徑的檔案是否存在,無論檔案路徑的長度如何,無論 Windows 上的普通路徑或 UNC 路徑如何。VBA可以嗎?
我試過的
在 VBA 中,檢查檔案是否存在的主要方法有兩種:
- 使用
Dir().
Dim isExists As Boolean
isExists = Dir("some\file\path") = vbNullString
- 使用
FileSystemObject(FSO)。
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim isExists As Boolean
isExists = objFSO.FileExists("some\file\path")
Dir()在這里沒有用,因為:
- 它不支持帶有 Unicode 字符的檔案路徑,例如中文字符。我使用的檔案路徑中有漢字。
- 對于長路徑,無論檔案是否存在,都會引發 File Not Found 錯誤。
FileSystemObject,另一方面,支持帶有 Unicode 字符的檔案路徑,但我無法讓它正確報告具有長路徑的檔案的檔案存在。
每當給出一個長路徑時,即使該檔案明顯存在于 Windows 檔案資源管理器中,也會objFSO.FileExists(...)回傳?!False
例如,
' Short paths: `True` if file exists and `False` otherwise, as expected.
objFSO.FileExists("C:\some\short\path") ' Windows native path.
objFSO.FileExists("\\server\drive\some\short\path") ' UNC path.
' Long paths: `False` no matter the file exists or not, unfortunately.
objFSO.FileExists("C:\some\very\long\path\that\may\have\unicode\characters") ' Windows native path.
objFSO.FileExists("\\server\drive\some\very\long\path\that\may\have\unicode\characters") ' UNC path.
我已經多次閱讀 Microsoft VBA 檔案,例如FileExists 方法,但沒有運氣。
請原諒我在這里插入一個小小的咆哮,在檔案中Dir()沒有提到它不支持 Unicode 字符的事實。來吧!
我的期望
誰能指出我可能遺漏了什么,或者回答這個問題是否可以用 VBA 解決?如果是這樣,我該怎么辦?如果您包含一些代碼示例來說明您的答案,那將是一件好事。謝謝!
uj5u.com熱心網友回復:
命名檔案、路徑和命名空間頁面說明以下內容:
在 Windows API(以下段落中討論的一些例外情況)中,路徑的最大長度為 MAX_PATH,定義為 260 個字符。
Windows API 有許多函式也有 Unicode 版本,以允許最大總路徑長度為 32,767 個字符的擴展長度路徑。這種型別的路徑由由反斜杠分隔的組件組成,每個組件都達到 GetVolumeInformation 函式的 lpMaximumComponentLength 引數中回傳的值(該值通常為 255 個字符)。要指定擴展長度的路徑,請使用“\?” 字首。例如,“\?\D:\非常長的路徑”。
因為你不能使用“\?” 帶有相對路徑的前綴,相對路徑總是限制為總共 MAX_PATH 個字符。
您可以嘗試使用 Windows API 函式,例如,您可以使用以下函式:
[DllImport("shlwapi", EntryPoint = "PathFileExists", CharSet = CharSet.Unicode)]
public static extern bool PathExists(string path);
在以下執行緒中閱讀有關可能解決方法的更多資訊:
- 當路徑太長時 File.Exists() 錯誤地回傳 false
- 檢查檔案/目錄是否存在:有更好的方法嗎?
uj5u.com熱心網友回復:
經過更多的研究,我想出了一個可行的 VBA 函式來做我想做的事。
如果有任何可以改進的地方,請隨時發表評論。
功能IsFileExists
Function IsFileExists(filepath As String) As Boolean
' Determine whether a file exists given its (absolute) file path, regardless
' of path length.
'
' filepath:
' The (absolute) file path to be checked for file existence. Can be
' native paths or UNC paths, short or long, extended with "\\?\" or
' "\\?\UNC" or not.
' Return: True if the file exists, False otherwise.
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
' FileSystemObject is sufficient for short paths.
If Len(filepath) <= 255 Then
IsFileExists = objFSO.FileExists(filepath)
Exit Function
End If
' Long paths.
If Left(filepath, 4) = "\\?\" Then
' Example: \\?\UNC\Server\Share\Some\Very\Long\Path
' Example: \\?\C:\Some\Very\Long\Path
' No action.
ElseIf Left(filepath, 2) = "\\" Then
' Example: \\Server\Share\Some\Very\Long\Path
filepath = objFSO.BuildPath("\\?\UNC\", Mid(filepath, 2))
Else
' Example: C:\Some\Very\Long\Path
filepath = objFSO.BuildPath("\\?\", filepath)
End If
IsFileExists = objFSO.FileExists(filepath)
End Function
簡要說明
正如 Eugene 的快速回答(非常感謝他)中提到的,Windows API 將檔案路徑的長度限制為 260 個字符,但是可以通過在路徑前加上\\?\或來擴展檔案路徑\\?\UNC\。
我上面的函式區分了短路徑和長路徑,并在需要時擴展路徑,然后使用 FileSystemObject 來檢查檔案是否存在。
該函式的一個警告是\\?\不能用于相對路徑,但我只考慮絕對路徑撰寫此函式。在輸入到此函式之前,可能需要將較長的相對路徑轉換為絕對路徑。
其他方法
PathFileExistsW在shlwapi
在撰寫本文時,我無法成功使用 VBAPathFileExistsW中shlwapi的 Declare Function 進行作業。我對此有點懷疑,因為微軟檔案說該函式的唯一引數接受“[a] 指向最大長度 MAX_PATH的以空結尾的字串的指標,該字串包含要驗證的物件的完整路徑。” (強調我的)。當我可以讓它測驗它時,我會更新。
參考
- Hans Passant 對 StackOverflow 問題“訪問具有長路徑的檔案(超過 260 個)”的回答
- 命名檔案、路徑和命名空間 | 微軟學習
- 最大路徑長度限制 | 微軟學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/529615.html
