Usando un sistema de archivos::ruta, ¿cómo se abre un archivo de forma multiplataforma?

3 minutos de lectura

Digamos que has usado el nuevo std::filesystem (o std::experimental::filesystem) código para buscar un archivo. Usted tiene un path variable que contiene la ruta de acceso completa a esta variable.

¿Cómo abres ese archivo?

Eso puede sonar tonto, pero considere la respuesta obvia:

std::filesystem::path my_path = ...;
std::ifstream stream(my_path.c_str(), std::ios::binary);

Esto no es garantizado trabajar. ¿Por qué? Porque en Windows, por ejemplo, path::string_type es std::wstring. Asi que path::c_str devolverá un const wchar_t*. Y std::ifstream pueden solamente tomar caminos con un const char* escribe.

Ahora resulta que este código realmente funcionará en VS. ¿Por qué? Debido a que Visual Studio tiene un extensión de la biblioteca que permite que esto funcione. Pero ese es un comportamiento no estándar y, por lo tanto, no portátil. Por ejemplo, no tengo idea si GCC en Windows ofrece la misma función.

Podrías intentar esto:

std::filesystem::path my_path = ...;
std::ifstream stream(my_path.string().c_str(), std::ios::binary);

Sólo Windows nos vuelve a confundir. Porque si my_path contenía caracteres Unicode, entonces ahora depende de configurar correctamente las cosas de la configuración regional ANSI de Windows. E incluso eso no necesariamente lo salvará si la ruta tiene caracteres de varios idiomas que no pueden existir en la misma configuración regional ANSI.

Boost Filesystem en realidad tenía un problema similar. Pero ampliaron su versión de iostreams para admitir pathdirectamente

¿Me estoy perdiendo de algo? ¿Agregó el comité una biblioteca de sistema de archivos multiplataforma sin agregar una forma multiplataforma de abierto archivos en él?

  • Es muy probable que la extensión se estandarice. Informe de defectos 2676. Podría haber sucedido la semana pasada.

    – Bo Person

    30 de junio de 2016 a las 13:40


  • haría basic_ifstream<path::value_type> stream(my_path); trabajo, o me estoy perdiendo algo allí? Seguro que no es bonito…

    – chris

    30 de junio de 2016 a las 13:45


  • @chris: No. El basic_ifstreamEl tipo de carácter se refiere al tipo de carácter del datos lee/escribe, no del camino que toma.

    – Nicolás Bolas

    30 de junio de 2016 a las 13:46

  • @NicolBolas, Cierto, mi error.

    – chris

    30 de junio de 2016 a las 13:46

Bo Persson señaló que este es el tema de un informe estándar de defectos de la biblioteca. Este defecto se ha resuelto y C++17 se distribuirá, lo que requiere implementaciones en las que path::value_type no es char para que sus tipos de flujo de archivos tomen const filesystem path::value_type*s además de lo habitual const char* versiones.

  • No lo ha hecho. Aunque probablemente se solucionará antes de que se publique C++17.

    – CT

    30 de junio de 2016 a las 19:43

  • Inaugurado: 2017-03-09 (open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2943)

    – Saludos y hth. – alf

    30 de abril de 2017 a las 12:18


  • traducción: utilice “std::ifstream stream(my_path.string());” o simplemente “std::ifstream stream(my_path);”. Si obtiene “tiene inicializador pero tipo incompleto”, no #include

    – AndrewStone

    20 abr a las 17:40


¿Ha sido útil esta solución?