Closed Noscka closed 4 weeks ago
Hi!
Usually similar problems occur when the archive contains items with very long paths, because when they're extracted the resulting path usually exceeds the Windows MAX_PATH
length limit.
Quoting Microsoft's documentation:
For example, the maximum path on drive D is "D:\some 256-character path string
" where " " represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
I've looked at your code example along with the file you're trying to extract, and this seems to be your case.
In particular, you're extracting the archive to the directory D:/Games/Gamma/extracted/GAMMA RC3
(31 characters, excluding the D:/
root), while the archive contains elements with very long paths (with a maximum of 226 characters); the longest output path is 257 characters, exceeding the 256 character limit.
Of course, if you extract the archive to a smaller path, you should not have the same problem.
There are some alternative workarounds to the path length limit:
\\?\
, e.g:
extractor.extract(L"D:/Games/Gamma/downloads/GAMMA RC3.7z", L"\\?\D:\Games\Gamma\extracted\GAMMA RC3");
\
, as this disables the automatic conversion of /
to \
performed by the Windows APIs.Bit7z also provides the build option BIT7Z_AUTO_PREFIX_LONG_PATHS
, which causes the library to automatically prepend the \\?\
prefix to the output paths when necessary (i.e. when a path exceeds MAX_PATH
).
To sum up:
const auto archivePath = L"D:/Games/Gamma/downloads/GAMMA RC3.7z";
// OK (no extracted item has a path exceeding the MAX_PATH).
extractor.extract(archivePath, L"D:/Test");
// Error (some extracted items have too long paths).
// Even the \\?\ prefix doesn't help in this case,
// as the path separator is not the native one, making the Windows APIs fail anyway.
extractor.extract(archivePath, L"D:/Games/Gamma/extracted/GAMMA RC3");
// Error, unless you configure bit7z with -DBIT7Z_AUTO_PREFIX_LONG_PATHS=ON.
extractor.extract(archivePath, LR"(D:\Games\Gamma\extracted\GAMMA RC3)");
// OK
extractor.extract(archivePath, LR"(\\?\D:\Games\Gamma\extracted\GAMMA RC3)" );
Hey,
Thank you very much for the quick response and with a lot of detail! It seems the main issue I had way using /
instead of \
. I apologize for not looking into this deep enough. Seems really simple now that I look at it.
No problem! Thank you for using bit7z!
bit7z version
4.0.x
Compilation options
BIT7Z_AUTO_FORMAT, BIT7Z_GENERATE_PIC, BIT7Z_REGEX_MATCHING, BIT7Z_STATIC_RUNTIME, BIT7Z_USE_NATIVE_STRING
7-zip version
v23.01
7-zip shared library used
7z.dll / 7z.so
Compilers
MSVC
Compiler versions
MSVC 2022
Architecture
x86_64
Operating system
Windows
Operating system versions
Windows 10
Bug description
I came back to a project, and it used to extract fine before, but now for some reason, I get an exception throw which is "Failed to open the output file: The system cannot find the path specified" with this specific 7z file. Some addition Info is there is also the error "D : The system cannot find the path specified" when looking at results from the "failedFiles()" function.
Steps to reproduce
Download the file Clone "https://github.com/Noscka/ProjectTest" Modify it to whatever paths you want (Although the paths might matter) Compile and run.
Expected behavior
To fully uncompress the file without any errors
Relevant compilation output
No response
Code of Conduct