Codificación incorrecta al llamar a shell

9

Estaba experimentando con un diagrama DOT e intenté hacer lo siguiente:

:! dot -Tpng -oFab.png %

Recibí un error porque mi nombre de archivo tiene un carácter especial (" ó" en "Fabricación"):

C:\windows\system32\cmd.exe /c ( dot -Tpng -oFab.png Fabricaci├│n.gv)
Error: dot: can't open Fabricaci├│n.gv
shell returned 2
Hit any key to close this window...

Como puede ver, el carácter especial se está cambiando por " ├│". Esto es con vim y gVim 7.4 en Win7 y NTFS, por lo que supongo que el nombre de archivo está en UTF16 . También supongo que cuando se invoca el shell / cmd, el nombre del archivo se interpreta como alguna otra codificación (gracias a Carpetsmoker por señalar que el valor predeterminado es la página de códigos 850 ).

¿Cómo puedo arreglar esto?

Claro, simplemente puedo cambiar el nombre del archivo, pero me gustaría saber por qué sucede esto y cómo corregirlo.

Actualización : acabo de encontrar esta pregunta en superuser.SE (gracias a los comentarios de @ ChristianBrabandt ), pero tampoco parece ayudar.

Roflo
fuente
1
Tengo curiosidad por saber si obtendría el mismo error al usar Vim en la línea de comando en Cygwin o MobaXterm (entornos portátiles similares a Unix para Windows). Sospecho que no. Puede haber una manera de arreglar esto para que Windows cmdacepte el nombre de archivo, pero instalar un entorno similar a Unix sería mi manejo preferido.
Comodín el
2
Por lo que leí, el valor predeterminado para cmd.exeno es unicode, sino la página de códigos 850 . También vea esta respuesta .
Martin Tournoij
Gracias @Carpetsmoker. Me tomé la libertad de actualizar mi pregunta con la información que proporcionó.
Roflo
No estoy completamente seguro, pero es posible que desee modificar la opción 'termencoding'.
Christian Brabandt
@ChristianBrabandt A menos que esté haciendo algo mal, eso no parece ayudar. Intenté configurar tenc en latin1, utf8 y cp850. Ninguno parece hacer el truco.
Roflo

Respuestas:

2

Respuesta corta

El problema radica en dot.exe. GraphViz puede abrir archivos con rutas Unicode en Linux pero no Windows, a menos que (tal vez) si se compila con Visual Studio 2005.

Investigación

La página de códigos está establecida en 850, Vim codificando en UTF-8.

ingrese la descripción de la imagen aquí

No da exactamente el mismo error, pero dot.exeparece recibir un argumento incorrecto. Intenté pasar el mismo nombre de archivo al otro programa.

ingrese la descripción de la imagen aquí

Y funcionó a la perfección. Ejecutar ambos dot.exey typedirectamente desde cmd.exeel mismo resultado, por lo que ni la consola de Windows ni Vim son el problema. Lo siguiente que pudo causar ese error fue en dot.exesí mismo. Mi sospecha era que simplemente no sabe cómo manejar los argumentos codificados Unicode correctamente, ya que ni siquiera todos los comandos de la consola lo hacen:

https://ss64.com/nt/chcp.html

Si necesita soporte completo de Unicode, use PowerShell. Todavía hay soporte MUY limitado para Unicode en el shell de CMD, las tuberías, la redirección y la mayoría de los comandos siguen siendo solo ANSI. Los únicos comandos que funcionan son DIR, FOR / F y TYPE, esto permite leer y escribir (UTF-16LE / BOM) archivos y nombres de archivos, pero no mucho más.

Busqué en la web si hay soporte para Unicode en GraphViz y descubrí que sí admite archivos Unicode pero nada sobre el soporte Unicode para los nombres de archivo. Ni encontré ningún informe en el rastreador de errores GraphViz ni publicaciones en el foro sobre alguien más interesado en leer un archivo con nombre Unicode. Así que lo busqué en la fuente. Aquí se dot.exeve el punto de entrada:

graphviz-2.40.1\cmd\dot\dot.c

int main(int argc, char **argv)
{
    . . .

/* --------------------> ARGS ARE BEING PASSED HERE */
    gvParseArgs(Gvc, argc, argv);

    . . .

Siguiendo argvpor la madriguera del conejo:graphviz-2.40.1\lib\common\args.c

int gvParseArgs(GVC_t *gvc, int argc, char** argv)
{
    int rv;
    if ((argc = neato_extra_args(gvc, argc, argv)) < 0)    return (1-argc);
    if ((argc = fdp_extra_args(gvc, argc, argv)) < 0)      return (1-argc);
    if ((argc = memtest_extra_args(gvc, argc, argv)) < 0)  return (1-argc);
    if ((argc = config_extra_args(gvc, argc, argv)) < 0)   return (1-argc);

/* -------------------->  HERE GO ALL NON-FLAG ARTUMENTS */
    if ((rv = dotneato_args_initialize(gvc, argc, argv)))  return rv;

    if (Verbose) gvplugin_write_status(gvc);
    return 0;
}

graphviz-2.40.1\lib\common\input.c

int dotneato_args_initialize(GVC_t * gvc, int argc, char **argv)
{
    for (i = 1; i < argc; i++) {
        if (argv[i] && argv[i][0] == '-') {

            . . .

/* -------------------->  JUST CASUALLY COPYING CHAR POINTERS */
        } else if (argv[i])
            gvc->input_filenames[nfiles++] = argv[i];
    }

Y finalmente graphviz-2.40.1\lib\common\input.c

graph_t *gvNextInputGraph(GVC_t *gvc)
{
    . . . .

/* -------------------->  OPENING THE FILES FOR READ WITH FOPEN */
    while ((fn = gvc->input_filenames[fidx++]) && !(fp = fopen(fn, "r")))  {

        . . .

    }

Como dice el MDSN:

La función fopen abre el archivo especificado por nombre de archivo. _wfopen es una versión de caracteres anchos de fopen ; Los argumentos de _wfopen son cadenas de caracteres anchos. _wfopen y fopen se comportan de manera idéntica de lo contrario. El simple uso de _wfopen no tiene ningún efecto en el conjunto de caracteres codificados utilizado en la secuencia de archivos.

En Visual C ++ 2005, fopen admite secuencias de archivos Unicode.

Lamentablemente, la única opción es cambiar el nombre del archivo.


fuente