SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C++/CLI: とある文字列の相互変換(コンバージョン)

マーシャル・ライブラリ、Encoder/Decoder、ICUによる文字列変換


文字コード変換

 .NETの世界では文字列としてはUnicodeだけ扱えればたいてい事足りるのですが、外の世界、たとえばテキストファイルではShift-JISやEUC-JP、電子メールではJIS(iso-2022-jp)が使われています。このようなテキストを扱うには、必要に応じて文字コードの変換を施さなくてはなりません。C#やVB.NETでテキストファイルを作ってみましょう。たとえばC#なら:

// C#でテキストファイルを作る
public class Program {
  public static void Main() {
    string contents = "4行の,文字列を,ファイルに,書きました";
    System.IO.File.WriteAllLines("trial.txt", contents.Split(','));
  }
}

 このとき、ファイル内の文字列の文字コードはUTF-8です。UTF-8以外の文字コードでテキストファイルを読み書きするにはStreamReader、StreamWriterのコンストラクト時、引数にEncodingを与えます(※Encodingがサポートする文字コード):

// Shift-JISテキストファイルを読む
{
  StreamReader reader(L"trial.txt", Encoding::GetEncoding(L"shift_jis"));
  String^ line;
  while ( (line = reader.ReadLine()) != nullptr ) {
    Console::WriteLine(line);
  }
}

 扱う文字列がファイル上ではなくメモリ上にある場合は、文字コードを司るクラスEncodingのメソッドGetEncoder/GetDecoderによって、「Unicodeから変換するEncoder」「Unicodeに変換するDecoder」を手に入れることができます。Encoder/Decoderを使った文字コード変換クラスUnicodeConverterをC++/CLIで実装したのが以下のコードです:

/*
 * System::Text::Encoder/Decoder による文字コード変換
 */
#include <string>

using namespace System;

ref class UnicodeConverter {
private:
  System::Text::Encoding^ encoding_;
  System::Text::Decoder^ decoder_;
  System::Text::Encoder^ encoder_;

public:
  UnicodeConverter(String^ name) {
    encoding_ = System::Text::Encoding::GetEncoding(name);
    encoder_ = nullptr;
    decoder_ = nullptr;
  }
  UnicodeConverter(int codepage) {
    encoding_ = System::Text::Encoding::GetEncoding(codepage);
    encoder_ = nullptr;
    decoder_ = nullptr;
  }

  std::string fromUnicode(const wchar_t* input, int size);
  std::wstring toUnicode(const char* input, int size);

  std::string fromUnicode(const std::wstring& input) 
    { return fromUnicode(input.data(), input.size()); }
  std::wstring toUnicode(const std::string& input)
    { return toUnicode(input.data(), input.size()); }
};

std::string UnicodeConverter::fromUnicode(const wchar_t* input, int size) {
  int bytesUsed;
  int charsUsed;
  bool completed;
  if ( encoder_ == nullptr ) encoder_ = encoding_->GetEncoder();
  std::string result(size*5, '\0');
  encoder_->Convert(
    const_cast<wchar_t*>(input), size, // 変換元のポインタとサイズ
    reinterpret_cast<unsigned char*>(&result[0]), result.size(), // 変換先のポインタとサイズ
    true, 
    charsUsed, bytesUsed, completed);
  result.resize(bytesUsed);
  return result;
}

std::wstring UnicodeConverter::toUnicode(const char* input, int size) {
  int bytesUsed;
  int charsUsed;
  bool completed;
  if ( decoder_ == nullptr ) decoder_ = encoding_->GetDecoder();
  std::wstring result(size,L'\0');
  decoder_->Convert(
    const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(input)), size, // 変換元のポインタとサイズ
    &result[0], result.size(), // 変換先のポインタとサイズ
    true,
    bytesUsed, charsUsed, completed);
  result.resize(charsUsed);
  return result;
}

/*
 * おためし
 */

#include <iostream>
#include <locale>

using namespace std;

int main() {

  wcout.imbue(locale("japanese"));

  // "JIS文字列" のJIS(iso-2022-jp)表現↓
  string jis = "\x4A\x49\x53\x1B\x24\x42\x4A\x38\x3B\x7A\x4E\x73\x1B\x28\x42";

  UnicodeConverter jis_converter(L"iso-2022-jp");

  // JIS → UNICODE
  wstring unicode = jis_converter.toUnicode(jis);
  wcout << L'[' << unicode << L']' << endl;

  // UNICODE → JIS
  string result = jis_converter.fromUnicode(unicode);
  if ( jis == result ) {
    wcout << L"元の文字列と一致しました!" << endl;
  }  

  // UNICODE → Shift-JIS
  UnicodeConverter sjis_converter(L"shift_jis");
  result = sjis_converter.fromUnicode(unicode);
  cout << '[' << result << ']' << endl;

}

次のページ
.NETに頼らない文字コード変換

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4774 2010/01/27 11:01

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー