0

Assume we have code like this:

boost::iostreams::mapped_file_source dev(paFileName.u8string().c_str());

where paFileName is a std::filesystem::path object.

On Windows, the internal character in std::filesystem::path is wchar_t, but boost::iostreams::mapped_file_source seems to only accept variant width character string. Therefore, we convert the fixed width wchar_t string to a variant width char string with method u8string.

The problem is that the conversion apparently causes the ctor of boost::iostreams::mapped_file_source unable to find the file in the filesystem, and the ctor will throw a boost::wrapexcept<std::ios_base::failure[abi:cxx11]> that says "failed opening file: The system cannot find the file specified."

How to fix this problem? Any suggestions? Thanks.

Cody
  • 609
  • 4
  • 21
  • Do you have some information? Like, what is an example filename? How do you get the filename? Is it hardcoded? How? – sehe Mar 14 '22 at 13:05
  • @sehe According to my own experience, any filenames that contain CJK character will have this problem, even if `std::filesystem::exists` confirms that the file does exist, given that the `std::filesystem::path` object is the argument instead of a standard string converted from the path object. – Cody Mar 15 '22 at 00:54

1 Answers1

0

According to the message of the compile-time error:

C:/msys64/mingw64/include/boost/iostreams/detail/path.hpp:138:5: note: declared private here
  138 |     path(const std::wstring&);
      |     ^~~~

Somehow Boost.Iostreams tried to convert the std::filesystem::path into a boost::iostreams::details::path but failed, because the conversion ctor that accepts the wide character string is not accessible. This problem doesn't happen on Linux, because the filesystem on Linux usually uses UTF-8 char strings as filenames. In contrast, on Windows the filenames are usually UTF-16 wchar_t strings.

My workaround is to avoid the conversion ctor mentioned above to be called. I gave a boost::filesystem::wpath instead of the original std::filesystem::path to Boost.Iostreams, hoping that the Boost version wpath is more acceptable to Boost.Iostreams.

boost::iostreams::stream<boost::iostreams::mapped_file_source> fin(
    boost::filesystem::wpath(static_cast<std::wstring>(paFileName))
);

And it works.

Cody
  • 609
  • 4
  • 21