boost property_tree로 UTF-8로 인코딩된 xml 읽고 쓰기

업데이트 2013-10-22) 좀 더 보기 좋은 방법을 추가했습니다.


BS가 간단한 유틸을 만들면서 설정파일을 매번 INI 형식을 사용하다가 이번에는 xml을 사용하였습니다.
사용한 라이브러리는 boost의 property tree
그런데 이렇게 무심코 사용했더니…


xml 헤더에는 인코딩이 utf-8이라고 나오지만 실제로는 Codepage 949의 ANSI 파일로 저장되네요.


그래서 UTF-8로 저장하기 위해서 아래와 같은 방법을 사용했습니다.

// 읽기
std::wstringstream ws;
ws.imbue(std::locale(std::locale::classic(), ".OCP", std::locale::ctype | std::locale::collate));
FILE* fp = nullptr;
if (_wfopen_s(&fp, _filepath.c_str(), L"rt, ccs=UTF-8") != 0)
	return false;
wchar_t buf[1024];
while (fgetws(buf, 1024, fp) != nullptr)
{
	ws << buf;
}
fclose(fp);
ws.seekg(0);
boost::property_tree::xml_parser::read_xml(ws, _settings, boost::property_tree::xml_parser::trim_whitespace);

// 쓰기
std::wostringstream wos;
wos.imbue(std::locale(std::locale::classic(), ".OCP", std::locale::ctype | std::locale::collate));
boost::property_tree::xml_parser::write_xml(wos, _settings, boost::property_tree::xml_writer_make_settings(L'\t', 1));
FILE* fp = nullptr;
if (_wfopen_s(&fp, _filepath.c_str(), L"wt, ccs=UTF-8") != 0)
	return;
fputws(wos.str().c_str(), fp);
fclose(fp);

메모리 상에서는 UCS16-LE로 하고 파일 입출력은 UTF-8로 하였습니다.
Windows에서 setlocale()이 UTF-8을 지원하면 저렇게 안해도 될텐데 말이죠…


좀 보기 안 좋습니다.


그래서 아래처럼 해봤습니다.


잘 되네요. (읽기는… 쓰기는 테스트 안했습니다. ㅎㅎㅎㅎㅎ 그냥 output stream에 L”가나다라” 했더니 BOM없는 UTF-8 문서로 저장은 잘 되네요.)

// 읽기
std::wifstream fin(_filepath.c_str());
fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf8<wchar_t>));
boost::property_tree::xml_parser::read_xml(fin, _settings, boost::property_tree::xml_parser::trim_whitespace);

// 쓰기
std::wofstream fout(_filepath.c_str(), new std::codecvt_utf8<wchar_t>));
boost::property_tree::xml_parser::write_xml(fout, _settings, boost::property_tree::xml_writer_make_settings(L'\t', 1));

글쓴이

BS

BS == Programmer