PHP는 내부적으로 문자열을 어떻게 표현합니까?


18

UTF8?
UTF16?

PHP의 문자열도 사용 된 인코딩을 추적합니까?

예를 들어이 스크립트를 봅시다. 내가 말해봐 :

$original = "शक्नोम्यत्तुम्";

실제로 어떻게됩니까?

분명히 나는 $original단지 7 문자를 포함하지 않을 것이라고 생각 합니다. 이 글리프는 각각 몇 바이트로 표시되어야합니다.

그런 다음

$converted = mb_convert_encoding ($original , "UTF-8");

어떻게 $converted됩니까? 어떻게 것입니다 $converted다를 수 $original?

$original다른 인코딩과 정확히 동일한 바이트 시퀀스 입니까?


1
어떤 버전의 PHP? PHP <6은 기본 UTF-8을 처리 할 수 ​​없습니다. 이 문제를 도와주는 패키지와 방법이 있습니다. utf-8 및 php로 Google을 즐기십시오. 그런 다음 PHP 대신 다른 플랫폼으로 전환하십시오. :)
Andrew T Finnell 2016 년

4
PHP <6? 여기에는 모든 버전의 PHP가 포함됩니다.
tdammers

1
또한 PHP UTF-8을 처리 할 수 있으며 전용 데이터 유형이 없으므로 수행중인 작업을 찾아야합니다.
tdammers 2016 년

답변:


22

PHP 문자열은 바이트 시퀀스 일 뿐이며 어떤 태그에도 인코딩이 없습니다. 문자열 값은 클라이언트 (HTTP를 통한), 데이터베이스, 파일 또는 소스 코드의 문자열 리터럴 등 다양한 소스에서 제공 될 수 있습니다. PHP는이 모든 것을 바이트 시퀀스로 읽으며 인코딩 정보를 추출하지 않습니다.

모든 데이터 소스와 대상이 동일한 인코딩을 사용하는 한 PHP에서 문자가 아닌 바이트 수를 계산하므로 문자열 위치가 잘못되어 멀티 바이트 인코딩을 사용하는 경우가 발생할 수 있습니다.

그러나 인코딩이 일치하지 않으면 (예 : UTF-8로 저장된 소스 파일에 문자열 리터럴을 작성한 다음 Latin-1이 필요한 데이터베이스로 전송) PHP는 변환을 수행하지 않습니다. 행복하게 바이트를 원시로 복사하십시오.

가장 순수한 해결책은 다음과 같습니다.

  • PHP의 내부 인코딩을 UTF-8로 설정하십시오.
  • 모든 소스 파일을 UTF-8로 저장하십시오.
  • UTF-8을 출력 인코딩으로 사용하십시오 (적절한 Content-type헤더 를 보내는 것을 잊지 마십시오 ).
  • UTF-8을 사용하도록 데이터베이스 연결을 설정하십시오 ( SET NAMES UTF8MySQL에서).
  • 가능하면 다른 모든 것을 UTF-8로 구성하십시오.
  • 제어 할 수없는 항목 (예 : 타사 웹 서비스)의 경우 인코딩을 알고 가능한 빨리 UTF-8로 변환 한 다음 가능한 한 늦게 다른 인코딩으로 다시 변환하십시오.

왜 UTF-8입니까? 모든 유니 코드 문자를 나타낼 수 있으므로 기존의 모든 7 비트 및 8 비트 인코딩을 대체하고 ASCII와 이진 호환 가능하므로 모든 유효한 ASCII 문자열도 유효한 UTF-8 문자열입니다 (단, vv는 아님) ).

귀하의 예에서 이런 일이 발생합니다.

먼저 소스 파일을 저장합니다. 텍스트 편집기는 아마도 UTF-8을 사용하도록 구성되어 있으므로 문자열 리터럴은 디스크에서 UTF-8로 인코딩됩니다. PHP는이 파일을 읽고 문자열을 일련의 바이트로 해석합니다. $original이제 7 바이트의 UTF-8로 인코딩 된 문자열을 보유하는데, 이는 바이트 순서 일뿐입니다 (각 문자는 2 바이트 이상으로 표시되므로 7 바이트 이상을 포함하지만). 그런 다음을 호출 echo $original하면 인코딩 된 문자열이 그대로 클라이언트로 전송됩니다. 클라이언트에게 UTF-8을 요구하라고 말하면 모든 것이 정상이지만, 그렇지 않은 경우 PHP는 차이점을 알 수있는 방법이 없으므로 브라우저에서 쓰레기가 발생합니다. 실험으로 다음을 시도하십시오.

$original = "शक्नोम्यत्तुम्";
echo strlen($original);

strlen 는 인코딩에 구애받지 않으며 고정 너비 8 비트 인코딩, 즉 문자 당 1 바이트를 가정하므로 문자가 아닌 바이트를 계산합니다.


따라서 $ converted는 동일한 문자열이지만 다른 인코딩을 나타냅니다. PhP가 저장하는 실제 원시 인코딩은 다릅니다.
user4951

2
PHP는 문자가 아닌 바이트를 저장하며 인코딩에 대해 전혀 모릅니다 (일부 라이브러리 함수는 수행하지만)
tdammers

1
아, "PhP"가 아니라 "PHP"입니다.
tdammers

2
원시 바이트가 동일한 경우 $ original과 $ converted의 차이점은 무엇입니까? 그것은 내가 묻는 것입니다.
user4951

2
오, 그게 당신의 뜻입니다. 예, 원시 바이트는 인코딩 변환에 따라 변경됩니다. PHP는 인코딩을 기억하지 않으므로 문자열을 utf-8에서 latin-1로 변환 한 다음 결과를 utf-8로 처리하면 이상한 결과가 나타납니다.
tdammers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.