아마도 논란의 여지가있는 질문이 무엇인지 물어볼 것입니다. “가장 인기있는 인코딩 중 하나 인 UTF-16이 유해한 것으로 간주되어야합니까?”
왜이 질문을합니까?
UTF-16이 실제로 가변 길이 인코딩이라는 사실을 알고있는 프로그래머는 몇 명입니까? 이것은 대리 쌍으로 표현되는 코드 포인트가 두 개 이상의 요소를 취하는 것을 의미합니다.
알아; 많은 애플리케이션, 프레임 워크 및 API는 Java의 문자열, C #의 문자열, Win32 API, Qt GUI 라이브러리, ICU 유니 코드 라이브러리 등과 같은 UTF-16을 사용합니다. BMP 외부 문자 (두 UTF-16 요소를 사용하여 인코딩해야하는 문자)
예를 들어 다음 문자 중 하나를 편집하십시오.
- 𝄞 ( U + 1D11E ) 음악 기호 G 음자리표
- U ( U + 1D565 ) 수학적 이중 타격 소형 T
- U ( U + 1D7F6 ) 수학적 모노 피스 디지트 제로
- Character ( U + 2008A ) 한자
설치 한 글꼴에 따라 일부를 놓칠 수 있습니다. 이 문자들은 모두 BMP (Basic Multilingual Plane) 외부에 있습니다. 이러한 문자가 보이지 않으면 유니 코드 문자 참조 에서 해당 문자를 살펴볼 수도 있습니다.
예를 들어, Windows에서 이러한 문자를 포함하는 파일 이름을 작성하십시오. UTF-16을 사용하는 다른 응용 프로그램에서 어떻게 작동하는지 보려면 “백 스페이스”를 사용하여 이러한 문자를 삭제하십시오. 나는 몇 가지 테스트를했는데 결과가 매우 나쁘다.
- Opera에서 편집에 문제가 있습니다 (백 스페이스에서 2 번 누르기 삭제 필요).
- 메모장에서 올바르게 처리 할 수 없습니다 (백 스페이스에서 두 번 눌러 삭제해야 함).
- 창 대화 상자에서 파일 이름 편집이 깨짐 (백 스페이스에서 2 번 누르기 필요)
- 모든 QT3 응용 프로그램은이를 처리 할 수 없습니다 . 하나의 기호 대신 두 개의 빈 사각형을 표시하십시오.
u'X'!=unicode('X','utf-16')
X는 BMP 외부의 문자 인 경우 일부 플랫폼에서 직접 사용될 때 이러한 문자를 잘못 인코딩 합니다.- Python 2.5 유니 코드 데이터는 파이썬이 UTF-16 유니 코드 문자열로 컴파일 될 때 이러한 문자에 대한 특성을 가져 오지 못합니다.
- StackOverflow는 유니 코드 문자로 직접 편집하면 텍스트에서 이러한 문자를 제거하는 것으로 보입니다 (이 문자는 HTML 유니 코드 이스케이프를 사용하여 표시됨).
- MaxLength로 제한되면 WinForms TextBox가 잘못된 문자열을 생성 할 수 있습니다 .
UTF-16을 사용하는 많은 응용 프로그램에서 이러한 버그를 쉽게 찾을 수 있습니다.
그렇다면 … UTF-16이 해로운 것으로 간주되어야한다고 생각하십니까?
답변
이것은 오래된 대답입니다. 최신 업데이트는 UTF-8 Everywhere 를
참조하십시오 .
의견 : 예, UTF-16은 유해한 것으로 간주해야합니다 . 그것이 존재하는 이유는 얼마 전에 widechar가 UCS-4가 될 것이라고 오도 된 믿음이 있었기 때문입니다.
UTF-8의 “anglo-centrism”에도 불구하고 텍스트에 유일하게 유용한 인코딩으로 간주되어야합니다. 프로그램의 소스 코드, 웹 페이지 및 XML 파일, OS 파일 이름 및 기타 컴퓨터 간 텍스트 인터페이스는 존재하지 않았어야한다고 주장 할 수 있습니다. 그러나 그들이 할 때 텍스트는 인간 독자만을위한 것이 아닙니다.
반면, UTF-8 오버 헤드는 지불해야하는 비용이 적지 만 상당한 이점이 있습니다. 로 문자열을 전달하는 알지 못하는 코드와의 호환성과 같은 장점 char*
. 이것은 좋은 일입니다. UTF-8보다 SHUTTER 인 유용한 문자는 UTF-8보다 적습니다.
다른 모든 인코딩은 결국 죽을 것이라고 믿습니다. 이것은 MS-Windows, Java, ICU, python이 그것을 좋아하는 것으로 사용하지 않는 것을 포함합니다. 오랜 연구와 토론 끝에 회사 의 개발 규칙은 OS API 호출을 제외한 모든 곳에서 UTF-16을 사용하는 것을 금지했으며 이는 응용 프로그램의 성능의 중요성과 Windows를 사용한다는 사실에도 불구하고 마찬가지입니다. 항상 가정 된 UTFF8 std::string
을 기본 UTF-16 으로 변환하기 위해 변환 기능이 개발되었으며 , Windows 자체 가 제대로 지원하지 않습니다 .
” 필요한 곳에 필요한 것을 사용하십시오 “라고 말하는 사람들에게는 모든 곳에서 동일한 인코딩을 사용하는 데 큰 이점이 있으며 그렇지 않으면 다른 이유가 없습니다. 특히 wchar_t
C ++에 추가 하는 것은 실수 라고 생각하고 C ++ 0x에 유니 코드를 추가 한 것도 마찬가지입니다. STL 구현에서 요구해야 할 것은 모든 std::string
또는 char*
매개 변수가 유니 코드 호환으로 간주 된다는 것입니다.
또한 ” 원하는 것을 사용하십시오 “접근 방식 에 위배 됩니다. 나는 그러한 자유의 이유가 없다. 텍스트의 주제에 대해 혼동이 많으므로이 모든 깨진 소프트웨어가 생깁니다. 위에서 말했듯이, 프로그래머는 UTF-8에 대한 적절한 합의에 따라 합의에 도달해야한다고 확신합니다. (나는 ASCII가 아닌 국가에서 왔으며 Windows에서 자랐으므로 마지막으로 종교적 근거를 기반으로 UTF-16을 공격 할 것으로 예상됩니다).
Windows에서 텍스트를 작성하는 방법과 컴파일 타임 검사 된 유니 코드 정확성, 사용 편의성 및 코드의 다중 플랫폼 향상을 위해 다른 사람들에게 권장하는 것에 대한 자세한 정보를 공유하고 싶습니다. 이 제안은 Windows에서 유니 코드를 사용하는 적절한 방법으로 일반적으로 권장되는 것과 다릅니다. 그러나 이러한 권장 사항에 대한 심도있는 연구를 통해 동일한 결론을 얻었습니다. 그래서 여기에 간다 :
- UTF-16을 허용하는 API에 인접한 점 이외의 곳을 사용
wchar_t
하거나std::wstring
다른 곳에서 사용하지 마십시오 . - 사용하지 마십시오
_T("")
또는L""
UTF-16 리터럴은 (이러한 IMO UTF-16 중단의 일환으로, 표준에서주의해야한다). - 유형, 함수 또는에 민감한 이들의 유도체 사용하지 마십시오
_UNICODE
과 같은 상수,LPTSTR
또는CreateWindow()
. - 그러나 WinAPI에 문자열을 자동 컴파일
_UNICODE
하는 것을 피하기 위해 항상 정의char*
std::strings
그리고char*
어디 프로그램에서 UTF-8로 간주됩니다 (그렇지 않으면 말했다하지 않은 경우)std::string
char * 또는 string literal을에 전달할 수 는 있지만 모든 문자열은convert(const std::string &)
입니다.-
widechars (
LPWSTR
) 를 허용하는 Win32 함수 만 사용하십시오 .LPTSTR
또는을 ( 를) 수락하는 사람은 절대 아닙니다LPSTR
. 이 방법으로 매개 변수를 전달하십시오.::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(정책은 아래의 변환 기능을 사용합니다.)
-
MFC 문자열로 :
CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call: std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse)); AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
-
Windows에서 파일, 파일 이름 및 fstream으로 작업 :
- 가족 에게 인수를 전달
std::string
하거나const char*
파일 이름을 지정 하지 마십시오fstream
. MSVC STL은 UTF-8 인수를 지원하지 않지만 비표준 확장명을 가지며 다음과 같이 사용해야합니다. -
std::string
로 다음std::wstring
과Utils::Convert
같이 인수를 변환하십시오 .std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
MSVC의 태도가
fstream
바뀔 때 변환을 수동으로 제거해야합니다 . - 이 코드는 다중 플랫폼이 아니며 나중에 수동으로 변경해야 할 수도 있습니다
- 자세한 정보는
fstream
유니 코드 리서치 / 토론 사례 4215를 참조하십시오. - 비 UTF8 컨텐츠로 텍스트 출력 파일을 생성하지 마십시오
fopen()
RAII / OOD 이유로 사용하지 마십시오 . 필요한 경우_wfopen()
위의 WinAPI 규칙을 사용하십시오 .
- 가족 에게 인수를 전달
// For interface to win32 API functions
std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/)
{
// Ask me for implementation..
...
}
std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/)
{
// Ask me for implementation..
...
}
// Interface to MFC
std::string convert(const CString &mfcString)
{
#ifdef UNICODE
return Utils::convert(std::wstring(mfcString.GetString()));
#else
return mfcString.GetString(); // This branch is deprecated.
#endif
}
CString convert(const std::string &s)
{
#ifdef UNICODE
return CString(Utils::convert(s).c_str());
#else
Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode
return s.c_str();
#endif
}
답변
유니 코드 코드 포인트는 문자가 아닙니다! 때로는 글리프도 아닙니다 (시각적 형태).
몇 가지 예 :
- “ⅲ”와 같은 로마 숫자 코드 포인트. “iii”처럼 보이는 단일 문자입니다.
- “á”와 같은 악센트 문자는 단일 결합 문자 “\ u00e1″또는 문자 및 분리 분음 부호 “\ u0061 \ u0301″로 표시 될 수 있습니다.
- 그리스어 소문자 시그마와 같은 문자는 단어 위치의 중간 ( “σ”)과 끝 ( “ς”)에 대해 서로 다른 형식을 갖지만 검색의 동의어로 간주되어야합니다.
- 컨텍스트에 따라 시각적으로 표시되거나 표시되지 않을 수 있고 의미 검색을 위해 무시되는 유니 코드 임의 하이픈 U + 00AD.
유니 코드 편집 권한을 얻는 유일한 방법 은 전문가가 작성한 라이브러리 를 사용 하거나 전문가가되어 직접 작성하는 것입니다. 코드 포인트를 세고 있다면 죄의 상태에 살고 있습니다.
답변
사용할 UTFF (Unicode Transformation Form)에 대한 간단한 경험 규칙이 있습니다.-저장 및 통신을위한 utf-8-데이터 처리를위한 utf-16-사용하는 대부분의 플랫폼 API가 utf-32 인 경우 utf-32 (UNIX 세계에서 일반적)
오늘날 대부분의 시스템은 utf-16 (Windows, Mac OS, Java, .NET, ICU, Qt)을 사용합니다. 이 문서도 참조하십시오 : http://unicode.org/notes/tn12/
“유해한 UTF-16″으로 돌아가서, 나는 말할 것입니다.
대리자를 두려워하는 사람들 (유니 코드를 가변 길이 인코딩으로 변환한다고 생각하는 사람들)은 문자와 합자, 변형 선택자를 결합하여 문자와 유니 코드 코드 포인트 간의 매핑을 매우 복잡하게 만드는 다른 (더 큰) 복잡성을 이해하지 못합니다. , 제어 문자 등
http://www.siao2.com/2009/06/29/9800913.aspx 에서이 시리즈를 읽고 UTF-16이 쉬운 문제가되는 방법을보십시오.
답변
네 그럼요.
왜? 그것은 코드 운동과 관련이 있습니다 .
Tom Christiansen 의 대규모 코퍼스 에서 이러한 코드 포인트 사용 통계 를 보면 BMP가 아닌 코드 포인트보다 큰 경우 8 비트 트랜스 BMP 코드 포인트가 몇 가지 순서로 사용됩니다.
2663710 U+002013 ‹–› GC=Pd EN DASH
1065594 U+0000A0 ‹ › GC=Zs NO-BREAK SPACE
1009762 U+0000B1 ‹±› GC=Sm PLUS-MINUS SIGN
784139 U+002212 ‹−› GC=Sm MINUS SIGN
602377 U+002003 ‹ › GC=Zs EM SPACE
544 U+01D49E ‹𝒞› GC=Lu MATHEMATICAL SCRIPT CAPITAL C
450 U+01D4AF ‹𝒯› GC=Lu MATHEMATICAL SCRIPT CAPITAL T
385 U+01D4AE ‹𝒮› GC=Lu MATHEMATICAL SCRIPT CAPITAL S
292 U+01D49F ‹𝒟› GC=Lu MATHEMATICAL SCRIPT CAPITAL D
285 U+01D4B3 ‹𝒳› GC=Lu MATHEMATICAL SCRIPT CAPITAL X
TDD dictum : “테스트되지 않은 코드는 코드가 손상되었습니다”를 받아 “실행되지 않은 코드는 코드가 손상되었습니다”로 바꾸고 프로그래머가 BMP가 아닌 코드 포인트를 처리하는 빈도를 생각하십시오.
가변 너비 인코딩으로 UTF-16을 처리하지 않는 것과 관련된 버그는 UTF-8의 해당 버그보다 훨씬 눈에 띄지 않을 수 있습니다. 일부 프로그래밍 언어는 여전히 UCS-2 대신 UTF-16을 제공한다고 보장하지 않으며 일부 고급 프로그래밍 언어는 코드 포인트 대신 코드 단위에 대한 액세스를 제공합니다 (C조차도 wchar_t
일부 플랫폼의 기능에 관계없이 를 사용하는 경우 코드 포인트 ).
답변
UTF-16을 해로운 것으로 생각하면 unicode에 대해 더 많이 이해해야 한다고 말합니다 .
주관적인 질문에 대한 나의 의견을 표명 한 것에 대해 공감 당 했으므로 자세히 설명하겠습니다. UTF-16에 대해 귀찮게하는 것이 정확히 무엇입니까? 모든 것이 UTF-8로 인코딩 된 것을 선호합니까? UTF-7? 아니면 UCS-4는 어떻습니까? 물론 특정 응용 프로그램은 모든 문자 코드를 처리하도록 설계되지는 않았지만 특히 오늘날의 글로벌 정보 도메인에서 국제 경계 간 통신에 필요합니다.
그러나 실제로 UTF-16이 혼란 스럽거나 부적절하게 구현 될 수 있기 때문에 (유니 코드가 확실 할 수 있음) 유해한 것으로 간주되는 경우, 어떤 문자 인코딩 방법이 무해한 것으로 간주됩니까?
편집 : 명확하게 : 왜 표준의 부적절한 구현이 표준 자체의 품질을 반영한다고 생각합니까? 다른 사람들이 나중에 지적했듯이, 응용 프로그램이 도구를 부적절하게 사용한다고해서 도구 자체에 결함이있는 것은 아닙니다. 이 경우 “var 키워드가 유해한 것으로 간주 됨”또는 “스레딩이 유해한 것으로 간주 됨”과 같은 것을 말할 수 있습니다. 저는이 질문이 표준의 품질과 본질을 많은 프로그래머들이 표준을 올바르게 구현하고 사용하는 데 어려움을 겪고 있다고 생각합니다. 이는 유니 코드 자체가 아닌 유니 코드의 작동 방식에 대한 이해 부족에서 비롯된 것입니다.
답변
Utf-16 인코딩에는 아무런 문제가 없습니다. 그러나 16 비트 단위를 문자로 취급하는 언어는 제대로 설계되지 않은 것으로 간주해야합니다. char
항상 문자를 나타내는 것은 아닌 ‘ ‘ 라는 유형의 유형을 갖는 것은 상당히 혼란 스럽습니다. 대부분의 개발자는 문자 유형이 코드 포인트 또는 문자를 나타낼 것으로 예상하기 때문에 BMP (Byound BMP) 문자에 노출되면 많은 코드가 중단 될 수 있습니다.
그러나 utf-32를 사용한다고해서 각 32 비트 코드 포인트가 항상 문자를 나타내는 것은 아닙니다. 문자 결합으로 인해 실제 문자는 여러 코드 포인트로 구성 될 수 있습니다. 유니 코드는 결코 사소하지 않습니다.
BTW. Utf-8이 제공되는 문자가 8 비트가 될 것으로 예상되는 플랫폼 및 응용 프로그램에는 동일한 종류의 버그가있을 수 있습니다.
답변
개인적으로 선택하는 것은 항상 UTF-8을 사용하는 것입니다. 거의 모든 것에 대한 Linux의 표준입니다. 많은 레거시 앱과 호환됩니다. 비 라틴 문자에 사용되는 여분의 공간은 다른 UTF 형식에 비해 매우 적은 오버 헤드가 있으며 라틴 문자에 대한 공간이 크게 절약됩니다. 웹상에서 라틴어는 최고가 될 것입니다. 그리고 원래 게시물의 주요 주장 중 하나를 해결하기 위해 거의 모든 프로그래머는 UTF-8에 때때로 멀티 바이트 문자가 있음을 알고 있습니다. 모든 사람이 이것을 올바르게 다루지는 않지만 UTF-16에 대해 말할 수있는 것 이상을 일반적으로 알고 있습니다. 그러나 물론 응용 프로그램에 가장 적합한 것을 선택해야합니다. 그렇기 때문에 처음에는 둘 이상이 있습니다.