Может ли идентификатор кодовой страницы UTF-8 (65001) отличаться на других компьютерах?

1479
Annonymus

Недавно я попытался объяснить другу, как создать простой командный файл в одну строку:

subst t: "X:\Example" 

На моей машине, которая хорошо работала в течение многих лет, но с их я столкнулся с проблемой: их имя содержало не-ASCII символы (точнее турецкие символы ı и ç), которые не были распознаны должным образом.

Простое решение этого, которое я хотел бы добавить

chcp 65001 

в верхней части файла, чтобы изменить активную кодовую страницу на UTF-8.

Но это не сработало. На их компьютере это вызвало сбой командной оболочки, которая его выполняла. Я заставил их попробовать несколько разных значений; Сбой 65000, но не 10000, и все значения ниже того, что я пробовал, также работали, но они не соответствовали тем же кодовым страницам, что и те же значения на моем компьютере. Их кодовая страница по умолчанию также отличалась (857 вместо 850, как на моем компьютере. Это имеет смысл, поскольку, согласно MSDN, 857 - это турецкая кодовая страница, а 850 - западноевропейская).

Я знаю, что некоторые кодовые страницы могут изменяться с компьютера на компьютер, но на странице MSDN прямо говорится, что следует использовать UTF-8, потому что другие страницы могут измениться (хотя есть печальная нехватка документации относительно того, как и когда они изменяются).

Это ложно? Может ли значение 65001 измениться? Если это так, то почему это может привести к сбою? Разве это не должно жаловаться на "Неверную кодовую страницу" в худшем случае? И если это действительно изменится, как можно узнать, какое значение использовать, чтобы получить его, или как еще можно заставить его принимать символы, не входящие в ASCII?

Я использую Windows 10 с английским языком (он был предустановлен с Windows 8.1 итальянский), в то время как мой друг использует Windows 7 турецкий.

2
`вверху файла` Вы сохранили командный файл в кодировке UTF-8? dxiv 7 лет назад 0
@dxiv да, я сделал (и удостоверился, что мой друг сделал также) Annonymus 7 лет назад 0

1 ответ на вопрос

2
JosefZ

По сути, Windows cmd(и ее интерпретатор пакетных сценариев) зависит от соответствия (текущей) активной кодовой страницы и кодировки пакетных сценариев. Например, если вы сохраняете сценарий Notepadв так называемой кодировке ANSI (что сильно зависит от языкового стандарта системы Windows ), вам следует запустить его в соответствующей кодовой странице, см. Справочник по API поддержки национальных языков (NLS) :

  • English (US) : ANSI соответствует ACP 1252(CP 437),
  • English (UK) : ANSI соответствует ACP 1252(CP 850),
  • Turkish : ANSI соответствует ACP 1254(CP 857),
  • Central Europe: ANSI соответствует ACP 1250(CP 852) и т. Д.

Ваше предположение верно:

Простое решение этого, которое я хотел бы добавить chcp 65001 в верхней части файла, чтобы изменить активную кодовую страницу на UTF-8. ... Но это не сработало.

К сожалению, ни Windows, cmdни пакетный интерпретатор не заботятся о метке байтового порядка и рассматривают ее как действительный символ - независимо от текущей активной кодовой страницы.
Следовательно, первая строка ( CHCP 65001команда в вашем случае) файла в кодировке UTF-8 загрязняется, если присутствует спецификация; Попытка выполнить такую грязную команду приведет к сообщению об ошибке ' CHCP' is not recognized as an internal or external command, operable program or batch file(errorlevel 9009).

Решение: Сохраните сценарий UTF-8, закодированный без BOM .
Обходной путь, если вы не можете сделать это (как Notepadвсегда пишет BOM): используйте пустую команду в качестве первой строки вашего скрипта, например, следующим образом:

@rem if this line is visibly executed then BOM is present >NUL 2>&1 @echo OFF rem save current code page to the `_chcp` variable for /F "tokens=2 delims=:" %%G in ('chcp') do set "_chcp=%%G" rem change active code page to UTF-8 (silently) CHCP 65001 >NUL rem echo this is UTF-8 encoded batch file %~nx0 echo( subst t: "D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ" subst dir /B /S t:\*.txt subst t: /D echo( echo( works as well for characters from Unicode Basic Multilingual Plane subst t: "D:\bat\Unusual Names\CJK\中文(繁體)" subst dir /B /S t:\*.txt subst t: /D echo( echo( works even for characters from Unicode Supplementary Multilingual Plane subst t: "D:\bat\Unusual Names\" subst dir /B /S t:\*.txt subst t: /D rem set active code page back to previously saved value (verbose) echo( CHCP %_chcp% 

Выход :

==> utf8.bat  ==> ´╗┐@rem if this line is visibly executed then BOM is present 1>NUL 2>&1  T:\: => D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ t:\ĞÜİŞÇÖçğüşöı.txt  works as well for characters from Unicode Basic Multilingual Plane T:\: => D:\bat\Unusual Names\CJK\中文(繁體) t:\chinese traditional.txt  works even for characters from Unicode Supplementary Multilingual Plane T:\: => D:\bat\Unusual Names\ t:\Mathematical Bold Script.txt  Active code page: 852 

Наконец, вы можете удалить первую строку (содержащую спецификацию) из вашего скрипта, используя moreкоманду следующим образом (обратите внимание chcp 65001перед запуском more +1 …):

==> chcp 65001 Active code page: 65001  ==> more +1 utf8.bat > utf8noBOM.bat  ==> utf8noBOM.bat  T:\: => D:\bat\Unusual Names\Türkçe (Türkiye)\çğüşöıĞÜİŞÇÖ t:\ĞÜİŞÇÖçğüşöı.txt  works as well for characters from Unicode Basic Multilingual Plane T:\: => D:\bat\Unusual Names\CJK\中文(繁體) t:\chinese traditional.txt  works even for characters from Unicode Supplementary Multilingual Plane T:\: => D:\bat\Unusual Names\ t:\Mathematical Bold Script.txt  Active code page: 65001  ==>