루비를 사용하여 오라클 데이터베이스의 완성형 자료를 mysql에 유니코드로 변환하여 저장한 것이 있습니다. 이것을 검색하는 프로그램을 C#으로 짤 일이 생겼는데 프로그램 자체는 그리 복잡하지 않게 만들수 있었습니다만 한글이 깨어져서 나오는 것이었습니다. 구글 검색에서도 신통한 답을 얻을 수 없던 차 이런저런 삽질 끝에 다음과 같은 코드로 깨어지지 않은 한글을 얻을 수 있었습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
OdbcCommand command = new OdbcCommand(query, connection); OdbcDataReader result; result = command.ExecuteReader(); first_field = result.GetString(0); // 이 방식은 한글이 깨어진다 long bsize = result.GetBytes(1, 0, null, 0, 0); byte[] raw = new byte[bsize]; result.GetBytes(1, 0, raw, 0, (int)bsize); // 자료의 byte 배열을 얻는다 Encoding scode = Encoding.UTF8; Encoding dcode = Encoding.GetEncoding(949); byte[] dBytes = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(949), raw); second_field = dcode.GetString(dBytes); // 이렇게 해야 한글이 깨어지지 않는다 |
GetString으로 받은 문자열은 어떻게 표시되는지와 상관없이 이미 유니코드이므로 인코딩을 변환할 수 없습니다. 흔히 하는 방법인 ASCII 코드로 변환하면 .NET에서 고약하게도 7bit 값으로 바꾸어버리므로 이것도 사용할수 없습니다. 결론적으로, GetString을 호출하지 않고 GetBytes 함수로 byte[] 배열을 직접 얻어서 코드를 변환해주는것이 포인트가 되겠습니다.
- 위의 결과는 MySQL connector/ODBC 3.51에서 얻은 것입니다. MySQL connector/Net과 MySQL connector/ODBC 5.XX 버젼에서는 제대로 실행되지 않을 수 있습니다. 되는 조합을 찾느라고 머리털 많이 뽑았습니다.
- field 값을 알아보기 위해서 IsDBNull 함수를 호출하면 그 필드값이 string으로 고정되어 버리고 이후 GetBytes 함수를 호출하면 오류가 발생합니다.
- Null 값에 GetBytes를 호출하면 InvalidCastException이 발생하므로 try, catch를 이용하여 처리합시다.
그나저나 윈도우즈에서 돌아가는 mysql이나 QueryBuilder 모두에서 utf8로 저장된 자료는 한글이 깨어져나옵니다. 위의 삽질 결과를 보면 윈도우즈에서 내부적으로는 유니코드를 쓰더라도 표시할때는 완성형한글을 쓴다는 결론을 얻을 수 있는데요, 과연 진실은 어떤것일런지.