Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::filesystem and Unicode under Linux and Windows

The following program compiles in Visual Studio 2008 under Windows, both with Character Set "Use Unicode Character Set" and "Use Multi-Byte Character Set". However, it does not compile under Ubuntu 10.04.2 LTS 64-bit and GCC 4.4.3. I use Boost 1.46.1 under both environments.

#include <boost/filesystem/path.hpp>
#include <iostream>

int main() {
  boost::filesystem::path p(L"/test/test2");
  std::wcout << p.native() << std::endl;
  return 0;
}

The compile error under Linux is:

test.cpp:6: error: no match for ‘operator<<’ in ‘std::wcout << p.boost::filesystem3::path::native()’

It looks to me like boost::filesystem under Linux does not provide a wide character string in path::native(), despite boost::filesystem::path having been initialized with a wide string. Further, I'm guessing that this is because Linux defaults to UTF-8 and Windows to UTF-16.

So my first question is, how do I write a program that uses boost::filesystem and supports Unicode paths on both platforms?

Second question: When I run this program under Windows, it outputs:

/test/test2

My understanding is that the native() method should convert the path to the native format under Windows, which is using backslashes instead of forward slashes. Why is the string coming out in POSIX format?

like image 930
Roger Dahl Avatar asked Mar 15 '11 02:03

Roger Dahl


2 Answers

Your understanding of native is not completely correct:

Native pathname format: An implementation defined format. [Note: For POSIX-like operating systems, the native format is the same as the generic format. For Windows, the native format is similar to the generic format, but the directory-separator characters can be either slashes or backslashes. --end note]

from Reference

This is because Windows allows POSIX-style pathnames, so using native() won't cause problems with the above.

Because you might often get similar problems with your output I think the best way would be to use your preprocessor, i.e.:

#ifdef WINDOWS
std::wostream& console = std::wcout;
#elif POSIX
std::ostream& console = std::cout;
#endif

and something similar for the string-class.

like image 135
filmor Avatar answered Nov 05 '22 03:11

filmor


If you want to use the wide output streams, you have to convert to a wide string:

#include <boost/filesystem/path.hpp>
#include <iostream>

int main() {
  boost::filesystem::path p(L"/test/test2");
  std::wcout << p.wstring() << std::endl;
  return 0;
}

Note that AFAIK using wcout doesn't give you Unicode output on Windows; you need to use wprintf instead.

like image 31
Philipp Avatar answered Nov 05 '22 02:11

Philipp