2011-03-15 10 views
9

El siguiente programa se compila en Visual Studio 2008 en Windows, ambos con el conjunto de caracteres "Usar conjunto de caracteres Unicode" y "Usar juego de caracteres de múltiples bytes". Sin embargo, no se compila en Ubuntu 10.04.2 LTS de 64 bits y GCC 4.4.3. Uso Boost 1.46.1 en ambos entornos.boost :: filesystem y Unicode en Linux y Windows

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

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

El error de compilación en Linux es:

test.cpp: 6: error: no puede competir con 'operador < <' en 'std :: wcout < < p.boost :: :: filesystem3 path :: native() '

Me parece que boost :: filesystem en Linux no proporciona una cadena de caracteres anchos en path :: native(), a pesar de que boost :: filesystem :: path se haya inicializado con un cuerda ancha Además, supongo que esto se debe a que Linux tiene por defecto UTF-8 y Windows a UTF-16.

Así que mi primera pregunta es, ¿cómo escribo un programa que usa boost :: filesystem y admite rutas Unicode en ambas plataformas?

Segunda pregunta: Cuando ejecuto este programa en Windows, se da salida:

/test/test2 

Mi entendimiento es que el método nativo() debe convertir la ruta al formato nativo en Windows, que está utilizando barras invertidas en su lugar de barras diagonales ¿Por qué está saliendo la secuencia en formato POSIX?

Respuesta

2

Su comprensión de native no es completamente correcto:

formato de nombre de ruta Nativo: formato definido Una implementación. [Nota: Para sistemas operativos similares a POSIX, el formato nativo es el mismo que el formato genérico. Para Windows, el formato nativo es similar al formato genérico, pero los caracteres separadores de directorios pueden ser barras diagonales o barras diagonales inversas. --end nota]

de Reference

Esto se debe a Windows permite nombres de ruta de estilo POSIX, así que usar native() no causará problemas con el anterior.

Debido a que a menudo se puede obtener problemas similares con su salida Creo que la mejor forma sería la de utilizar el preprocesador, es decir .:

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

y algo similar para la clase cadena.

+0

Gracias por su respuesta. Mirando esto un poco más, parece que utilizar cout y no tener caracteres anchos es el camino a seguir en Linux, ya que todo es UTF-8 allí.Pero en la consola de Windows, usar wcout, aunque compila, no mostraría los caracteres Unicode correctamente. Para que funcione, aparentemente hay varios obstáculos que uno debe atravesar. –

+0

La consola de Windows es capaz de mostrar Unicode en formato UTF-16 pero su fuente predeterminada no es capaz, debe cambiar la configuración de la consola a una fuente Unicode. También en mi experiencia, todas las rutas a través de las funciones C I/O de Windows pasan estúpidamente por un cuello de botella de codificación de 8 bits que no es Unicode, incluso si pasas UTF-16 y la salida está en UTF-16. Es posible que pueda hacer algunos ajustes y pasar algunos parámetros para evitarlo ... pero llamar a las API de salida de consola de Windows "anchas" es mucho más fácil. – hippietrail

1

Si desea utilizar los flujos de salida de ancho, usted tiene que convertir a una amplia cadena:

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

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

Tenga en cuenta que yo sepa usar wcout no le da salida Unicode en Windows; necesita usar wprintf en su lugar.

+1

Gracias por la respuesta. He realizado algunas investigaciones sobre wcout y parece que simplemente convierte los caracteres anchos en caracteres angostos al eliminar los bytes altos antes de enviar los caracteres estrechos resultantes a stdout. Aparentemente, así es como se define wcout en la Biblioteca estándar de C++, pero todavía no he podido verificar esto. Si es así, realmente no hace nada útil en ninguna plataforma. –

+0

path :: string() no es funcionalmente equivalente a path: native(). Me pregunto por qué no hay camino :: wnative()? –

+0

@Roger: "wcout realmente no hace nada útil en ninguna plataforma". - Estoy de acuerdo. Para imprimir cadenas Unicode en Windows, debe usar ['wprintf'] (http://blogs.msdn.com/b/michkap/archive/2008/03/18/8306597.aspx). Acerca de 'wnative': Por definición, hay exactamente un formato nativo canónico en cada plataforma, que puede ser una cadena ancha (Windows) o estrecha (Unix). – Philipp

0

Prueba esto:

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

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