Может ли идентификатор кодовой страницы 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 соответствует ACP1252
(CP437
),English (UK) :
ANSI соответствует ACP1252
(CP850
),Turkish :
ANSI соответствует ACP1254
(CP857
),Central Europe:
ANSI соответствует ACP1250
(CP852
), так далее.
Ваше предположение верно:
Простое решение этого, которое я хотел бы добавить
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
==>