获取OEM和Ansi中每个区域设置的代码页

时间:2018-10-04 20:13:24

标签: c# python windows locale ansi

如何获取每个语言环境的代码页(不仅限于我的语言环境)?

我正在python / c#/ c(更喜欢python或c#)中寻找一个简单的函数,以便为每个语言环境找到我想要的Ansi和OEM中的代码页。

1 个答案:

答案 0 :(得分:1)

在C中,从Windows Vista开始,您可以通过locale name查询GetLocaleInfoEx的信息。用于查询ANSI和OEM代码页的locale information constants分别是LOCALE_IDEFAULTANSICODEPAGE(0x1004)和LOCALE_IDEFAULTCODEPAGE(0x000B)。您可以通过EnumSystemLocalesEx枚举所有系统语言环境名称,并在回调中查询每个语言环境的ANSI和OEM代码页。

在Python脚本中,您可以通过ctypes调用这些函数。例如:

import ctypes
from ctypes import c_int
from ctypes.wintypes import BOOL, DWORD, LPVOID, LPWSTR, LPARAM, WCHAR

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

CP_ACP = 0
CP_OEMCP = 1
LOCALE_NAME_USER_DEFAULT = None
LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale"
LOCALE_RETURN_NUMBER = 0x20000000
LOCALE_IDEFAULTCODEPAGE = 0x0000000B
LOCALE_IDEFAULTANSICODEPAGE = 0x00001004
LOCALE_SENGLISHLANGUAGENAME = 0x00001001
LOCALE_SENGLISHCOUNTRYNAME = 0x00001002

LOCALE_ENUMPROCEX = ctypes.WINFUNCTYPE(BOOL, 
    LPWSTR, # lpLocaleString
    DWORD,  # dwFlags
    LPARAM) # lParam

def _check_zero(result, func, args):
    if not result:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

kernel32.EnumSystemLocalesEx.errcheck = _check_zero
kernel32.EnumSystemLocalesEx.argtypes = (
    LOCALE_ENUMPROCEX, # lpLocaleEnumProcEx
    DWORD,             # dwFlags
    LPARAM,            # lParam
    LPVOID)            # lpReserved

LCTYPE = DWORD
kernel32.GetLocaleInfoEx.errcheck = _check_zero
kernel32.GetLocaleInfoEx.argtypes = (
    LPWSTR, # lpLocaleName,
    LCTYPE, # LCType,
    LPVOID, # lpLCData,
    c_int)  # cchData

def get_language(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    length = kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHLANGUAGENAME, 
        None, 0)
    language = (WCHAR * length)()
    kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHLANGUAGENAME, 
        language, length)
    return language.value

def get_country(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    length = kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHCOUNTRYNAME, 
        None, 0)
    country = (WCHAR * length)()
    kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHCOUNTRYNAME, 
        country, length)
    return country.value

def get_acp(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    cp_ansi = DWORD()
    kernel32.GetLocaleInfoEx(locale, LOCALE_IDEFAULTANSICODEPAGE | 
        LOCALE_RETURN_NUMBER, ctypes.byref(cp_ansi), 
        ctypes.sizeof(cp_ansi) // ctypes.sizeof(WCHAR))
    return cp_ansi.value

def get_oemcp(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    cp_oem = DWORD()
    kernel32.GetLocaleInfoEx(locale, LOCALE_IDEFAULTCODEPAGE | 
        LOCALE_RETURN_NUMBER, ctypes.byref(cp_oem), 
        ctypes.sizeof(cp_oem) // ctypes.sizeof(WCHAR))
    return cp_oem.value

def list_system_locales():
    system_locales = []
    @LOCALE_ENUMPROCEX
    def enum_cb(locale, flags, param):
        system_locales.append((locale, 
            get_language(locale), get_country(locale), 
            get_acp(locale), get_oemcp(locale)))
        return True
    kernel32.EnumSystemLocalesEx(enum_cb, 0, 0, None)
    return sorted(system_locales)

请注意,仅Unicode的语言环境没有ANSI或OEM代码页。在这种情况下,返回的值是针对当前系统ANSI和OEM代码页的,即CP_ACP(0)和CP_OEMCP(1)。例如,印度(IN)的北印度语(hi)语言是仅Unicode的语言环境:

>>> (get_acp('hi-IN'), get_oemcp('hi-IN')) == (CP_ACP, CP_OEMCP)
True