Niepoprawne kodowanie podczas wywoływania powłoki

9

Eksperymentowałem ze schematem DOT i próbowałem wykonać następujące czynności:

:! dot -Tpng -oFab.png %

óWystąpił błąd, ponieważ moja nazwa pliku ma znak specjalny („ ” w „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...

Jak widać, znak specjalny zmienia się na „ ├│”. Dzieje się tak z vimem i gVimiem 7.4 pod Win7 i NTFS, więc zakładam, że nazwa pliku to UTF16 . Zakładam również, że podczas wywoływania powłoki / cmd nazwa pliku jest interpretowana jako inne kodowanie (dzięki Carpetsmoker za wskazanie, domyślnie jest to strona kodowa 850 ).

Jak mogę to naprawić?

Jasne, mogę po prostu zmienić nazwę pliku, ale chciałbym wiedzieć, dlaczego tak się dzieje i jak to naprawić.

Aktualizacja : Właśnie znalazłem to pytanie w superuser.SE (dzięki opinii @ ChristianBrabandt ), ale wydaje się, że to również nie pomaga.

Roflo
źródło
1
Jestem ciekawy, czy ten sam błąd wystąpiłby przy użyciu Vima w wierszu poleceń w Cygwin lub MobaXterm (przenośne środowiska uniksowe dla Windows). Nie podejrzewam Może istnieć sposób, aby to naprawić, więc Windows cmdakceptuje nazwę pliku, ale instalowanie środowiska podobnego do Uniksa byłoby moją preferowaną obsługą.
Wildcard
2
Z tego, co przeczytałem, domyślną wartością cmd.exenie jest Unicode, ale strona kodowa 850 . Zobacz także tę odpowiedź .
Martin Tournoij,
Dzięki @Carpetsmoker. Pozwoliłem sobie zaktualizować moje pytanie o informacje, które podałeś.
Roflo
Nie jestem do końca pewien, ale możesz chcieć ulepszyć opcję „termencoding”.
Christian Brabandt
@ChristianBrabandt Chyba że robię coś złego, to chyba nie pomaga. Próbowałem ustawić tenc na latin1, utf8 i cp850. Wydaje się, że żaden nie rozwiązuje problemu.
Roflo,

Odpowiedzi:

2

Krótka odpowiedź

Problem leży w dot.exe. GraphViz może otwierać pliki ze ścieżkami Unicode w systemie Linux, ale nie w systemie Windows, chyba że (być może), jeśli jest skompilowany z Visual Studio 2005.

Badania

Strona kodowa jest ustawiona na 850, kodowanie Vim na UTF-8.

wprowadź opis zdjęcia tutaj

Nie podaje dokładnie tego samego błędu, ale dot.exewydaje się, że otrzymuje niewłaściwy argument. Próbowałem przekazać tę samą nazwę pliku do innego programu.

wprowadź opis zdjęcia tutaj

I zadziałało w sam raz. Wykonanie obu dot.exei typebezpośrednio z cmd.exetego samego wyniku daje taki sam wynik, więc ani konsola Windows, ani Vim nie stanowią problemu. Następną rzeczą, która mogła spowodować ten błąd, była dot.exesama. Podejrzewałem, że po prostu nie wie, jak poprawnie obsługiwać argumenty zakodowane w Unicode, ponieważ nawet nie wszystkie polecenia konsoli:

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

Jeśli potrzebujesz pełnej obsługi Unicode, użyj PowerShell. Nadal BARDZO ograniczona jest obsługa Unicode w powłoce CMD, potokowanie, przekierowywanie, a większość poleceń jest nadal tylko ANSI. Jedynymi poleceniami, które działają, są DIR, FOR / F i TYPE, pozwala to na odczyt i zapis (UTF-16LE / BOM) plików i nazw plików, ale niewiele więcej.

Szukałem w Internecie, czy w GraphViz istnieje obsługa Unicode i okazało się, że obsługuje ona pliki Unicode , ale nic na temat obsługi plików Unicode. Ani nie znalazłem żadnych raportów na temat narzędzia do śledzenia błędów GraphViz ani postów na forum o tym, że ktoś jest zainteresowany czytaniem pliku o nazwie Unicode. Sprawdziłem to w źródle. Oto jak dot.exewygląda punkt wejścia:

graphviz-2.40.1\cmd\dot\dot.c

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

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

    . . .

W argvdół króliczej nory: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];
    }

I na koniec 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")))  {

        . . .

    }

Jak stwierdza MDSN:

Funkcja fopen otwiera plik określony przez nazwę pliku. _wfopen jest wersją fopen o szerokim zakresie znaków ; argumentami _wfopenłańcuchy szerokich znaków. _wfopen i fopen zachowują się identycznie inaczej. Samo użycie _wfopen nie ma wpływu na kodowany zestaw znaków używany w strumieniu plików.

W Visual C ++ 2005, fopen obsługuje strumienie plików Unicode.

Niestety jedyną dostępną opcją jest zmiana nazwy pliku.


źródło