windows 路径名太长,无法打开?

a8jjtwal  于 2022-12-05  发布在  Windows
关注(0)|答案(5)|浏览(258)

这是执行的屏幕截图:

正如您所看到的,错误显示目录“JSONFiles/Apartment/Rent/dubizzleabudhabiperproperty”不存在。
但请看我的档案:

文件夹肯定在那里。

更新2

该代码

self.file = open("JSONFiles/"+ item["category"]+"/" + item["action"]+"/"+ item['source']+"/"+fileName + '.json', 'wb') # Create a new JSON file with the name = fileName parameter
        line = json.dumps(dict(item)) # Change the item to a JSON format in one line
        self.file.write(line) # Write the item to the file

更新
当我把文件名改成一个小一点的文件名时,它能工作,所以问题是因为路径的长度。请问解决办法是什么?

xmakbtuz

xmakbtuz1#

常规DOS路径限制为MAX_PATH(260)个字符,包括字符串的终止字符NUL。通过使用以\\?\前缀开头的扩展长度路径,可以超过此限制。此路径必须是Unicode字符串,完全限定,并且只能使用反斜杠作为路径分隔符。根据Microsoft的file system functionality comparison,最大扩展路径长度为32760个字符。单个文件或目录名最多可为255个字符(UDF文件系统为127个字符)。扩展UNC路径也支持\\?\UNC\server\share
例如:
第一个
请参阅MSDN上的下列页面:

背景
Windows调用NT运行时库函数RtlDosPathNameToRelativeNtPathName_U_WithStatus将DOS路径转换为NT本地路径。如果我们使用open(即CreateFile)上述路径,并在后一函数上设置断点,我们可以看到它如何处理以\\?\前缀开头的路径。

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装置前置词\??\取代\\?\,并将字串复制到原生UNICODE_STRING

0:000> dS b450f9ec18
000000b4`536b7de0  "\??\C:\Temp\test.txt"

如果您使用//?/而不是\\?\,则路径仍然限制为MAX_PATH个字符。如果太长,则RtlDosPathNameToRelativeNtPathName返回状态代码STATUS_NAME_TOO_LONG(0xC 0000106)。
如果您使用\\?\作为前缀,但在路径的其余部分使用斜杠,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/终端服务)这变成了一个虚拟前缀。对象管理器处理这个前缀的方法是首先检查目录\Sessions\0\DosDevices\[LOGON_SESSION_ID]中登录会话的DOS设备链接,然后检查系统-\Global??目录中的宽DOS设备链接。
请注意,前者是登录会话,而不是Windows会话。登录会话目录都在Windows会话0(即Vista+中的服务会话)的DosDevices目录下。因此,如果您有一个用于非提升登录的Map驱动器,您会发现它在提升的命令提示符下不可用,因为您的提升令牌实际上是用于不同的登录会话。
一个DOS设备链接的例子是\Global??\C: =〉\Device\HarddiskVolume2。在这种情况下,DOS C:驱动器实际上是一个到HarddiskVolume2设备的符号链接。
下面简要介绍系统如何解析路径以打开文件。假设我们调用WinAPI CreateFile,它将转换后的NT UNICODE_STRING存储在OBJECT_ATTRIBUTES结构中,并调用系统函数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管理器函数IoCreateFile,它又调用未记录的对象管理器API ObOpenObjectByName。这将执行解析路径的工作。对象管理器以\??\C:\Temp\test.txt开始。然后它将其替换为\Global??\C:Temp\test.txt。接下来,它将解析到C:符号链接,并且必须重新开始(重新解析)最终路径\Device\HarddiskVolume2\Temp\test.txt
一旦对象管理器到达HarddiskVolume2设备对象,解析就交给I/O管理器,它实现Device对象类型。I/O DeviceParseProcedure创建File对象和具有major function codeIRP_MJ_CREATEI/O Request Packet (IRP)(一个打开/创建操作)。这通过IoCallDriver发送到设备驱动程序。如果设备实现了重分析点,(例如,接合挂载点、符号链接等),并且该路径包含重解析点,则必须将解析的路径重新提交给对象管理器,以便从头解析。
设备驱动程序将使用进程令牌(或线程,如果模拟)的SeChangeNotifyPrivilege(几乎总是存在并启用)绕过访问检查,同时遍历目录。然而,最终访问设备和目标文件必须通过安全描述符来允许,这是通过SeAccessCheck验证的。除了简单的文件系统,如FAT32不支持文件安全。

lmvvr0a8

lmvvr0a82#

下面是关于@ ErykSun解决方案的Python 3版本。

def winapi_path(dos_path, encoding=None):
    if (not isinstance(dos_path, str) 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

Python 3将unicode类型重命名为str,旧的str类型已替换为bytes。NameError: global name 'unicode' is not defined - in Python 3

2guxujil

2guxujil3#

添加帮助我解决类似问题的解决方案:Python版本= 3.9,Windows版本= 10专业版。
我遇到了一个文件名本身的问题,因为它对于python的open内置方法来说太长了。我得到的错误是路径根本不存在,尽管我使用了'w+'模式来打开(它应该打开一个新文件,不管它是否存在)。
我找到了这个guide,它通过快速更改windows的注册表编辑器(特别是组策略)解决了这个问题。
不要忘记更新操作系统组策略以使其立即生效,可在here中找到指南。
希望这有助于未来的搜索,因为这篇文章是相当古老的。

iklwldmw

iklwldmw4#

出现此错误的原因可能有多种。请确保以下几点:
1.文件夹(JSONFiles)的父目录与Python脚本的目录相同。
1.即使文件夹存在,并不意味着单个文件也存在。验证文件夹,并确保文件名与Python代码试图访问的文件名完全匹配。
如果你仍然面临一个问题,分享的结果“dir”命令对最内层的文件夹,你试图访问。

fhity93d

fhity93d5#

对我很有效

import os
str1=r"C:\Users\sandeepmkwana\Desktop\folder_structure\models\manual\demodfadsfljdskfjslkdsjfklaj\inner-2djfklsdfjsdklfj\inner3fadsfksdfjdklsfjksdgjl\inner4dfhasdjfhsdjfskfklsjdkjfleioreirueewdsfksdmv\anotherInnerfolder4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\5qbbbbbbbbbbbccccccccccccccccccccccccsssssssssssssssss\tmp.txt"
print(len(str1)) #346

path = os.path.abspath(str1)

if path.startswith(u"\\\\"):
    path=u"\\\\?\\UNC\\"+path[2:]
else:
    path=u"\\\\?\\"+path

with open(path,"r+") as f:
    print(f.readline())

如果您在Windows中遇到长路径(超过258个字符)问题,请尝试此操作。

相关问题