결과 전 : 한글 깨짐
결과 후 : 한글 깨짐 해결
해결방법
QString::fromLocal8bit(str)
해결 전 코드
str.append(QString("채널 : %1\n").arg(cam.channel));
str.append(QString("카메라 이름 : %1 \n").arg(cam.name));
str.append(QString("IP : %1\n").arg(cam.url));
str.append(QString("전력 : %1 W\n").arg(cam.power));
해결 후 코드
str.append(QString::fromLocal8Bit("채널 : "));
str.append(QString::number(cam.channel));
str.append(" \n");
str.append(QString::fromLocal8Bit("카메라 이름 : "));
str.append(cam.name);
str.append(" \n");
str.append(QString::QString("IP : %1\n").arg(cam.url));
str.append(QString::fromLocal8Bit("전력 : "));
str.append(QString::number(cam.power));
str.append("W \n");
참고 링크 (여러가지 방안 제시해줌) :
https://kojin777.tistory.com/1
Qt 한글 출력
함수를 만들었네요 QString kor(char* str){ QString korStr = QString::fromLocal8Bit(str); return korStr; } 이 함수의 내용은 일단은 문자열이 들어와서, 그것을 QString 으로 만들어서 되돌려 주는 것으로 만..
kojin777.tistory.com
2019년 9월에 한글 깨지는 문제가 발생했는데 2021년 6월인 지금도 유사한 문제가 발생했다.
2019년 문제는 테스트 코드만 신경쓰면 되니까 나름 쉬웠는데, 이번에는 카메라로부터 전달되는 데이터 형식도 고려해서 코드를 짜야한다.
Unicode, Utf8, Utf16에 대한 배경지식부터 정리하자.
그리고 현재 카메라로부터 전달된 값은 xml에 저장된다. 따라서 TiXmlElement가 값을 어떻게 인코딩해서 저장하고 읽어오는지 살펴봐야한다.
이후에는 내가 테스트로 넣어주는 가상 데이터는 어떤 형식으로 저장되는지 살펴봐야하고,
네트워크 쪽에서 데이터 변환해주는 부분도 살펴봐야 한다.
1. 배경 지식 정리
2. TinyXML 인코딩 방식
3. Window Visual stuido 에서 가상 데이터 형식
1. 배경 지식
QString은 16비트의 QChars의 string으로 저장한다. 각각의 QChar는 UTF-16 코드 유닛에 해당된다.
Unicode는 오늘날 대부분의 writing 시스템에서 사용되는 국제적인 표준이다. unicode는 US-ASCII 와 Latin-1를 포함하는 상위 집합이다. 모든 US-ASCII/Latin-1 문자가 같은 code로 사용 가능하게 해준다.
뒷 배경에는, QString은 암시적 공유(copy-on-write)를 사용한다. 암시적 공유를 사용함으로써 메모리 사용량을 줄일 수 있고, 불필요한 데이터 복사를 피할 수 있다. 이것은 또한 8-bit 문자를 저장하는 대신 16-bit 문자를 저장하면서 생기는 어쩔 수 없는 과부하를 줄여준다.
알파벳은 1Byte로 구현하며, 한글과 같은 대부분의 non-ascii 문자 셋은 lead byte와 tail byte로 구성되는 2-byte를 사용한다.
유니코드는 UTF-8, UTF-16, UTF-32 이렇게 세 가지로 분류되는데, 뒤의 숫자는 Code point 기본 단위를 지칭하는 것이다. 이를테면 UTF-8의 단위는 8-bit, 즉 1-Byte만으로 표현을 하며 , 이외의 문자들은 8-bit씩 덧붙여가는 방식으로 추가하고 있는데, 이처럼 Leading Byte와 Tail byte로 구성되는 문자셋은 Surrogate Pair라고 지칭한다.
한편, UTF-8은 문자셋에 따라 2-byte, 3-byte, 4-byte로 구성되어 있으며 한글은 3-byte로 구성된다. 그리고 UTF-16은 2-Byte가 기본단위이므로 2-Byte 이외의 문자는 2-Byte를 다시 추가한 4-Byte로 Code Point를 지정하고 있다. UTF-16 초창기 버전에서는 오직 2-Byte 단위였지만, 현재는 2byte와 4byte(Surrogate Pairs)로 구성된다. 마지막으로 UTF-32는 기본 단위가 32BIT, 즉 모든 Code point가 4byte이다.
UTF-16에서 한글 '가'의 code point는 'ac' '00'으로 2-byte이며, UTF-8에서는 'ea' 'b0' '80' 이렇게 3-byte이다.
웹에서 대다수의 플랫폼이 UTF8을 사용하고 있으며, OS의 경우 윈도우는 UTF-16, 리눅스는 UTF-8을 쓰고 있다.
2. TinyXML write/read 데이터 형식
TinyXML 은 파일 인코딩을 UTF-8로 열고 유니코드로 인코딩하여 재 저장하여 문자가 깨지지 않도록 한다.
3. Window Visual stuido 에서 가상 데이터 형식
테스트 결과 윈도우 visual studio 환경에서 QString안에 큰따옴표(")를 통해 QString을 생성할 경우, 8-bit단위로 생성된다. 이와 같은 이유로 위에 2019년 예제에서도 8bit 문자열을 unicode로 변환해줬더니 글자 깨지는 문제가 해결된 것이다. 8bit문자열 -> unicode 변환 메소드는 Qt에서 제공해준다. fromLocal8Bit()
다른 예시를 들자면, QString("한글테스트").toUtf8() 와 같이 타입 변환을 해주면 안되고, 아래와 같이 해줘야 한다.
QString::fromLocal8bit("한글테스트").toUtf8() "한글테스트" 라는 문자열의 데이터 타입을 local 8bit 에서 unicode로 변환해주고, 그 이후에 utf8()로 변환해준다.
틀린 방법 : QString("한글테스트").toUtf8()
옳은 방법 : QString::fromLocal8bit("한글테스트").toUtf8()
참고 링크:
https://doc.qt.io/qt-5/qstring.html#details
https://blog.daum.net/bc399/23