python读取路径太长_路径名太长,无法打开?
常規DOS路徑限制為MAX_PATH(260)個字符,包括字符串的終止字符NUL。通過使用以\\?\前綴開頭的擴展長度路徑,可以超過此限制。此路徑必須是完全限定的Unicode字符串,并且只能使用反斜杠作為路徑分隔符。根據Microsoft的file system functionality comparison,最大擴展路徑長度為32760個字符。單個文件或目錄名最多可以包含255個字符(UDF文件系統為127個字符)。擴展的UNC路徑也支持為\\?\UNC\server\share。
例如:import os
def winapi_path(dos_path, encoding=None):
if (not isinstance(dos_path, unicode) and
encoding is not None):
dos_path = dos_path.decode(encoding)
path = os.path.abspath(dos_path)
if path.startswith(u"\\\\"):
return u"\\\\?\\UNC\\" + path[2:]
return u"\\\\?\\" + path
path = winapi_path(os.path.join(u"JSONFiles",
item["category"],
item["action"],
item["source"],
fileName + ".json"))>>> path = winapi_path("C:\\Temp\\test.txt")
>>> print path
\\?\C:\Temp\test.txt
請參閱MSDN上的以下頁面:
背景
Windows調用NT運行庫函數RtlDosPathNameToRelativeNtPathName_U_WithStatus將DOS路徑轉換為本機NT路徑。如果上面的路徑在后面的函數上設置了斷點,我們可以看到它如何處理以前綴\\?\開頭的路徑。Breakpoint 0 hit
ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus:
00007ff9`d1fb5880 4883ec58 sub rsp,58h
0:000> du @rcx
000000b4`52fc0f60 "\\?\C:\Temp\test.txt"
0:000> r rdx
rdx=000000b450f9ec18
0:000> pt
ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus+0x66:
00007ff9`d1fb58e6 c3 ret
結果將\\?\替換為NT DOS設備前綴\??\,并將字符串復制到本機^{}:0:000> dS b450f9ec18
000000b4`536b7de0 "\??\C:\Temp\test.txt"
如果使用//?/而不是\\?\,則路徑仍限制為MAX_PATH個字符。如果太長,則RtlDosPathNameToRelativeNtPathName返回狀態代碼STATUS_NAME_TOO_LONG(0xc000106)。
如果使用\\?\作為前綴,但在路徑的其余部分使用斜杠,則Windows不會為您將斜杠轉換為反斜杠:Breakpoint 0 hit
ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus:
00007ff9`d1fb5880 4883ec58 sub rsp,58h
0:000> du @rcx
0000005b`c2ffbf30 "\\?\C:/Temp/test.txt"
0:000> r rdx
rdx=0000005bc0b3f068
0:000> pt
ntdll!RtlDosPathNameToRelativeNtPathName_U_WithStatus+0x66:
00007ff9`d1fb58e6 c3 ret
0:000> dS 5bc0b3f068
0000005b`c3066d30 "\??\C:/Temp/test.txt"
正斜杠是NT命名空間中的有效對象名字符。它由Microsoft文件系統保留,但您可以在其他命名的內核對象中使用正斜杠,這些對象存儲在\BaseNamedObjects或\Sessions\[session number]\BaseNamedObjects中。另外,我不認為I/O管理器對設備和文件名中的保留字符強制執行策略。這取決于設備。也許有人有一個Windows設備,它實現了一個名稱空間,允許在名稱中使用正斜杠。至少可以創建包含正斜杠的DOS設備名。例如:>>> kernel32 = ctypes.WinDLL('kernel32')
>>> kernel32.DefineDosDeviceW(0, u'My/Device', u'C:\\Temp')
>>> os.path.exists(u'\\\\?\\My/Device\\test.txt')
True
你可能想知道\??意味著什么。這曾經是對象名稱空間中DOS設備鏈接的實際目錄,但從NT 5(或NT 4 w/Terminal Services)開始,這就變成了一個虛擬前綴。對象管理器通過首先檢查目錄\Sessions\0\DosDevices\[LOGON_SESSION_ID]中登錄會話的DOS設備鏈接,然后檢查目錄\Global??中的系統范圍的DOS設備鏈接來處理此前綴。
請注意,前者是登錄會話,而不是Windows會話。登錄會話目錄都在Windows會話0的DosDevices目錄下(即Vista+中的服務會話)。因此,如果您有用于非提升登錄的映射驅動器,您將發現它在提升的命令提示符中不可用,因為提升的令牌實際上用于不同的登錄會話。
DOS設備鏈接的一個例子是\Global??\C:=>;\Device\HarddiskVolume2。在這種情況下,DOS C:驅動器實際上是指向HarddiskVolume2設備的符號鏈接。
以下是系統如何處理解析路徑以打開文件的簡要概述。假設我們調用WinAPI CreateFile,它將轉換后的NT UNICODE_STRING存儲在^{}結構中,并調用系統函數NtCreateFile。0:000> g
Breakpoint 1 hit
ntdll!NtCreateFile:
00007ff9`d2023d70 4c8bd1 mov r10,rcx
0:000> !obja @r8
Obja +000000b450f9ec58 at 000000b450f9ec58:
Name is \??\C:\Temp\test.txt
OBJ_CASE_INSENSITIVE
NtCreateFile調用I/O管理器函數^{},后者反過來調用未記錄的對象管理器API ObOpenObjectByName。這是解析路徑的工作。對象管理器以\??\C:\Temp\test.txt開頭。然后它用\Global??\C:Temp\test.txt替換它。接下來它解析到C:符號鏈接,并且必須重新開始(重新解析)最終路徑\Device\HarddiskVolume2\Temp\test.txt。
一旦對象管理器到達HarddiskVolume2設備對象,解析就傳遞給I/O管理器,它實現Device對象類型。I/O的ParseProcedure{}創建File對象和major function codeIRP_MJ_CREATE(打開/創建操作)的I/O Request Packet (IRP)由設備堆棧處理。這將通過^{}發送到設備驅動程序。如果設備實現重分析點(例如連接裝入點、符號鏈接等),并且路徑包含重分析點,則必須將解析的路徑重新提交給對象管理器,以便從一開始就進行分析。
設備驅動程序將在遍歷目錄時使用進程標記(或者如果模擬則使用線程)的SeChangeNotifyPrivilege(幾乎總是存在并啟用)來繞過訪問檢查。但是,最終對設備和目標文件的訪問必須由安全描述符來允許,該描述符通過^{}進行驗證。除了像FAT32這樣的簡單文件系統不支持文件安全之外。
總結
以上是生活随笔為你收集整理的python读取路径太长_路径名太长,无法打开?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何实现通知_ExASIC:
- 下一篇: java内部float,Java中的fl