libiconv で文字セット自動認識

2010 年 3 月 3 日 by 村山 俊之
ご無沙汰ぶりです…。
以前、wchar_t はどうにも使い物にならないからどうしよう、といった記事を書いたのですが、その続きのお話です。
表題の通りで、 libiconv を用いて文字セットを自動認識する処理のサンプルを書いてみました。詳しい経緯はTicket 内で逐次コメントしています。
この投稿の続きを読む »
ご無沙汰ぶりです…。
以前、wchar_t はどうにも使い物にならないからどうしよう、といった記事を書いたのですが、その続きのお話です。
表題の通りで、 libiconv を用いて文字セットを自動認識する処理のサンプルを書いてみました。詳しい経緯はTicket 内で逐次コメントしています。
この投稿の続きを読む »
とりあえず黒字です。わーい。
Boost セットアップ中… orz
実は先日 HDD に物理的損傷らしきものを見つけてしまいまして、必要なデータだけ抜き取ってフォーマットを試みたら見事にエラーで止まりやがったのでやむなく新しいのに交換したのですよ。
ここ最近は忙しかったり体調も安定しなかったりだったので otoco の方の作業はずっと停滞してました…。やっと朝まともに起きれるぐらいに体調は戻ってきたので、そろそろ otoco の作業も復活したいなぁと思いつつ…。
ああそうだ、Linux も使えるように grub 入れ直さないと…。
今メインでやっているお仕事を紹介してくださった友人に、CiNii という論文検索サイトを教えて頂きました。むしろ今まで知らなかったのかよぐらいの勢いなのですが…(^_^;A それはさておき。
個人的に気になっているのは、今 otoco でやろうとしている、楽譜情報と演奏情報 (シーケンス情報) を融合するデータ表現に関する研究が、MML なりそれ以外なりのアプローチで行われているのか、ということです。別に、既に行われているなら otoco を作るのはやめようとかそういう話ではないのですが、先行研究があれば参考にはさせて頂きたいな、とは思うわけです。
今のところそれらしい研究成果はまだ見つけられていないのですが、music macro language で検索してみたところ、面白いものを見つけました。かなり画期的な概念に基づく MML、その名も「PMML」です。
この投稿の続きを読む »
otoco に限らず、 PC 上で動作するプログラムの多くは、テキストを処理することを目的の一部またはすべてとしています。 otoco の場合は特に、どこの誰とも分からない人が MML を書き、それを読み込んで XML やら SMF やらオーディオやら楽譜やらに変換することを目的としているので、どこの誰が MML を (あるいは XML を直接) 書いても問題なく処理できるよう、文字セットの扱いには丁重でなければなりません。
当初の方針として、 otoco では内部コードに Unicode を使用し、その物理型は wchar_t で扱うつもりでいました。この辺、C/C++ でのクロスプラットフォーム開発に慣れていないと陥りやすい罠であるように思うのですが… 現状の wchar_t ははっきり言ってクロスプラットフォーム開発には向いていないものといわざるを得ないようです。
とりあえず確認しているのは Windows の VC++ 2008 と Linux の gcc だけなのですが、それだけでも調べた限りで以下のような相違点がありました。
Boost ライブラリの Ubuntu へのインストールは容易でした。単に libboost-dev パッケージを aptitude install してあげるだけです。
問題は、前回も書いた通り、 apt からインストールできる Boost のバージョンは通常で 1.34.1、最新のものを選んでも 1.37.0 になってしまう、ということです。
そこで、 otoco の開発に影響する範囲で、バージョン間にどの程度の差異があるのか、調べておくことにしました。
とりあえず今思いつくのは正規表現まわりだけだったのでまだそこしか調べていないのですが (空文字列マッチは何気に影響範囲大きそうですが…古いバージョンで統一しておけばとりあえず問題にはならないかな…)、実際に開発が進めば利用範囲が広がり、都度気づく部分も増えていくかもしれません。上記ページはその都度更新して行く予定です。
昨日、一昨日はメインの仕事の都合で朝が早かったので、こっちの作業はちょっと pending してました。
cl.exe コマンドを直接呼んでビルドする方法については調査完了しました。必須オプションが何気に多いですね…。実際にはあれに最適化オプションなりデバッグオプションなりがくっつくことになります。
で、今度は Ubuntu でのセットアップを調べているのですが、ここで問題発覚。どうやら Ubuntu での boost ライブラリのメインバージョンはまだ 1.34.1 で止まっているようです…。もしかしたら Debian を始め、多くの Linux ディストリビューションにおいても同様の状況なのかもしれません。当初は最新の 1.39.0 を利用する予定でしたが、事実上の汎用性が損なわれる可能性もあるので (さすがにライブラリを手動でインストールしてくれ、とやる訳にもいかないですからね…)、互換性を確認しつつ、バージョンについては考慮しなければならないかもしれません。
インストールして動かして、というあたりはまだこれから調査するところです…。
Windows 環境で Boost ライブラリをセットアップしてみました。明日は Linux 環境でもセットアップを行い、技術メモとしてまとめる予定です。
で、せっかくなので、試しに簡単なサンプルを作って動作確認をしてみました。
#include <iostream>
#include <fstream>
#include <string>
#include <boost/regex.hpp>
using namespace std;
using namespace boost;
void escapeHtml(const string &src, string &modified);
int main(int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
ifstream fin(argv[i]);
if (fin.bad() || fin.fail())
{
cerr << argv[0] << ": Can't open " << argv[i] << "." << endl;
continue;
}
while (!fin.eof())
{
string line;
getline(fin, line);
string modified;
escapeHtml(line, modified);
cout << modified << endl;
}
}
return 0;
}
void escapeHtml(const string &src, string &modified)
{
modified.clear();
sregex_iterator last_it;
for (sregex_iterator it(src.begin(), src.end(), regex("[<>&\"]")); it != sregex_iterator(); it++)
{
modified += it->prefix().str();
string sub = (*it)[0].str();
switch (sub[0])
{
case '<': modified += "<"; break;
case '>': modified += ">"; break;
case '&': modified += "&"; break;
case '"': modified += """; break;
default: assert(0); break;
}
last_it = it;
}
modified += last_it == sregex_iterator() ? src : last_it->suffix().str();
}
Boost.Regex の regex_iterator を用いたテストです。よーするに、コマンドに指定したファイルの HTML エスケープ処理を施してコンソールに書き出すプログラムです。
上記のプログラムを test.cpp などのファイル名で保存し、そのまま Visual Studio 2008 コマンドプロンプト上で
cl test.cpp
とやってみましたが、これだけではコンパイルできませんでした。どうやら、 Visual Studio のオプションダイアログでヘッダーファイルやライブラリの参照先ディレクトリを設定しても、その設定が参照されるのは Visual Studio の IDE からビルドを実行した場合のみのようです。あるいは、環境変数 INCLUDE や LIB を設定してあげればこれでコンパイルできるのかも知れません。その辺はまた追々調べてみますが、最終的には .configure に --boost-prefix といったようなオプションを設ける、といった形の対応になるのではないかとも思います。
ちなみに、これと同等の (しかもより確実に動作する) プログラムを Perl で記述すると、以下の通りになります (この書き方はしかし Unix 風環境限定ですが)。
#!/usr/bin/perl -p
s/[<>&"]/'&'.{qw(< lt > gt & amp " quot)}->{$&}.';'/eg;
うあー、やっぱりスクリプト言語は便利だなー (汗。
egtra 様、ご指摘感謝です。仰る通り、 string::getline() を使った方がスマートなので、その通りに修正させて頂きました。
…なんか、UI と I/O の関係図にデータの流れも含まれてるなぁ。これだったらデータの流れ図要らなかったかも…。ていうか、基本的にはここでやりたかったのは必要な UI の可視化なので、実行時オプション、設定ファイル、警告出力、そして各種操作が、各処理とどう関係するか、という部分だけ書いて、データの流れは含めるべきではなかったかも…。あと端子で書いた 3つの出力もデータの流れ図で示すべきだったかも…。データの流れ図ではファイルと見分けが付かないしなぁ…。
なんだけど、いまいちしっくりこないので、まだ未公開です…。ちょっと時間をかけすぎてしまった (1時間以上オーバー^_^;)。
…操作と入出力がごっちゃになっちゃってるなぁ。入力はファイルを規定しているのに出力はそれを規定しないからアンバランスになってるんだろうな。操作が処理を呼び出す関係と処理による入出力の関係は切り離さないとな。出力はどうやって示そう? コネクタが良いのかなぁ… (以上独り言)