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

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

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 турецкий.

1 ответ

Решение

В основном, 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 (Равно 9009).

Решение: сохраните свой сценарий в кодировке UTF-8 без спецификации.
Обходной путь, если вы не можете сделать это (как 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

==>
Другие вопросы по тегам