I was working on a bigger project using the recursive_directory_iterator
of std::filesystem
, when I stumbled upon this seemingly unknown/unfixable error.
I simplified the project to the bare minimum to recreate the error. Another questioner found a solution in providing the skip_permission_denied
option, which does nothing for me.
The exception is not limited to this file, it happens for random other files too, if I delete this one, for instance. Though it occurs for the same file every time if I decide not to delete it.
If I use the continue button on Visual Studio three times, it is actually able to continue the traversal of files.
What would be a proper way to address this error? And what could potentially cause this?
I removed all exception handling for readability, but the error occurs at the start of the for
loop once it reaches this file.
#define NOMINMAX
#include <string>
#include <iostream>
#include <filesystem>
#include <windows.h>
#include <fstream>
#include <winbase.h>
#include <numeric>
#include <string_view>
#include <vector>
#include <shlobj_core.h>
//#include <combaseapi.h>
namespace fs = std::filesystem;
using namespace std;
void startWinXSearch(string argv)
{
string pathToFolder = argv;
cout << pathToFolder << endl;
for (auto& el : std::filesystem::recursive_directory_iterator(pathToFolder, std::filesystem::directory_options::skip_permission_denied)) {
cout << el << endl;
}
}
int main(int argc, char* argv[])
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
string test = "C:\\Sciebo";
startWinXSearch(test);
}
UPDATE: This is what I get from using wcout
. No idea what this is supposed to mean. Is it that there's an invisible file there?!
The Error thrown currently is No mapping for the Unicode character exists in the target multi-byte code page
. If I find a solution or workaround I'll update it here.
FINAL UPDATE: I got it. Take a look at one of the comments ^^ It originated from invisible Unicode characters infront of a random file from my phone :D I even got a fix/workaround for it!
CodePudding user response:
Seems to be this error:
ERROR_NO_UNICODE_TRANSLATION
1113 (0x459)
No mapping for the Unicode character exists in the target multi-byte code page.
System Error Codes (1000-1299) (WinError.h) - Win32 apps | Microsoft Docs
Try renaming the file.
CodePudding user response:
Clearly you are getting a non-permission failure on some of the files. So, you will need to either:
- wrap the failing code in a
try..catch
, eg:
#define NOMINMAX
#include <string>
#include <iostream>
#include <filesystem>
#include <windows.h>
#include <shlobj_core.h>
//#include <combaseapi.h>
namespace fs = std::filesystem;
void startWinXSearch(const std::string &pathToFolder)
{
std::cout << pathToFolder << std::endl;
try {
for (auto& el : fs::recursive_directory_iterator(pathToFolder, fs::directory_options::skip_permission_denied)) {
std::cout << el << std::endl;
}
}
catch (const fs::filesystem_error &) {
// handle error as needed...
}
}
int main()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
startWinXSearch("C:\\Sciebo");
CoUninitialize();
}
- use
recursive_directory_iterator
's non-throwing constructor andincrement()
method (which means you can't use arange-for
loop), eg:
#define NOMINMAX
#include <string>
#include <iostream>
#include <filesystem>
#include <windows.h>
#include <shlobj_core.h>
//#include <combaseapi.h>
namespace fs = std::filesystem;
void startWinXSearch(const std::string &pathToFolder)
{
std::cout << pathToFolder << std::endl;
std::error_code ec;
fs::recursive_directory_iterator dir(pathToFolder, fs::directory_options::skip_permission_denied, ec);
if (ec) {
// handle error as needed...
}
else {
auto iter = std::begin(dir);
auto iter_end = std::end(dir);
while (iter != iter_end) {
std::cout << *iter << std::endl;
iter.increment(ec);
if (ec) {
// handle error as needed...
}
}
}
}
int main()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
startWinXSearch("C:\\Sciebo");
CoUninitialize();
}
Either way, you can then analyze the fs::filesystem_error
or std::error_code
to find out what kind of OS error is actually occurring.
CodePudding user response:
SOOOOOOO
I got the answer.. The problem originates from invisible (atleast for win10) unicode characters infront of a file ^^
How do you prevent that from crashing your programm? EZ, we first build our iterating for loop. EG like this:
for (auto& dirEntry : fs::recursive_directory_iterator(pathToFolder))
// Iterates over every file/folder in the path of the executable and its subdiretories
{
const std::wstring currentPath = dirEntry.path().c_str();
string output = wide_string_to_string(currentPath);
std::cout << output << endl;
}
Then we require a suited and well done wstring -> string conversion ^^ I got this one from some site I just can't find again..
std::string wide_string_to_string(const std::wstring& wide_string)
{
if (wide_string.empty())
{
return "";
}
const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), (int)wide_string.size(), nullptr, 0, nullptr, nullptr);
if (size_needed <= 0)
{
throw std::runtime_error("WideCharToMultiByte() failed: " std::to_string(size_needed));
}
std::string result(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wide_string.at(0), (int)wide_string.size(), &result.at(0), size_needed, nullptr, nullptr);
return result;
}
Our Main would look something like this.
int main()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
startWinXSearch("C:\\Users\\wwwgi\\OneDrive\\Dokumente\\test");
CoUninitialize();
}
Ofc you can also work with argv values, you just gotta format the raw path the appropiate way ^^ you can even use wmain wchar_t argv[] if you like that! If you are unsure about the formatting you can try to format it with .path() and .string()/.c_string() :)