Trf (Tcl/Tk Extension)

●Trfとは?
ここで取りあげるTrfは、 Andreas Kupries さんによって開発された、 文字データの変換処理を中心とした各種コマンドをTcl処理系に追加するTclの拡張ライブラリです。 Tcl 7.6の時代(1996年10月)から配布されてきましたが、 Tcl 8.1までの版はTcl処理系にパッチを当てる必要がありました。 このパッチはTcl 8.2で本体に「逆輸入」されたので、 8.2以降の版ではパッチ不要でインストールするだけで使えるようになっています。
現在のTrfはオープンソースプロジェクトとなって、 こちらがホームページですが、 コマンド解説などドキュメントは、 Kupries さんの個人ページ時代のホームページであった、 こちらのみに置かれています。 ここからUNIX用のソースアーカイブと、 これまたTcl/Tkの大重鎮であるJan Nijtmansさん達によってコントリビュートされた WindowsやLinux用のバイナリアーカイブがダウンロードできます。 最新バージョンは2.1.4(2009/10/26)で、 またTcl/TkのWindows用バイナリ配布であるActiveTclにも含まれています。
なおTRFというのは非常に意味の多い頭字語の1つです。 わが国では20世紀の終わり頃に「Tetsuya-komuro Rave Factory」 というのがありました。代表曲は、もちろん(私の主観で)「EZ DO DANCE」(1993)であります。 なので現在はTclのTrfはオープンソースのプロジェクト名の通り、 TclTrfと呼ぶのが混乱が少ないのかもしれません。

●TrfCryptとは?
以前の版のTrfには、 現在の版と比べて暗号化に関するコマンドが含まれていましたが、 米国輸出規制(軍事転用可能なソフトウェア技術)に対する配慮のため、 現在では「Trfcrypt」なる別のパッケージとして同じサイトから配布されています。 私自身も暗号化については興味がちょっぴりあるわけでして、 TrfCryptについても別のページでふれてみます。

●テキストデータの変換を行うコマンド

  • bin
  • oct
  • hex
  • uuencode
  • base64
他にもまだありますが、この5つが便利そうなテキストの変換コマンドです。 これらのコマンドはテキストデータ (画像などのバイナリも可)をそれぞれ2進数表記、8進数表記、16進数表記、 uuencode、Base64の各形式に変換(エンコード)・復元(デコード)するコマンドです。 使い方は全部同じで、
  # エンコード
  set result [bin -mode encode $source]
  # デコード
  set result [bin -mode decode $source]
これでOKです。 ですが、-modeはデータより先に指定しないといけないことに注意してください。
  bin $source -mode encode
はエラーになります。
簡単な例で試してみましょう。

#! /usr/local/bin/tclsh
package require Trf

set s  "Hello, Trf World."
set b1 [bin -mode encode $s]
set o1 [oct -mode encode $s]
set h1 [hex -mode encode $s]
set u1 [uuencode -mode encode $s]
set b641 [base64 -mode encode $s]
puts "$b1\n$o1\n$h1\n$u1\n$b641\n"
set b2 [bin -mode decode $b1]
set o2 [oct -mode decode $o1]
set h2 [hex -mode decode $h1]
set u2 [uuencode -mode decode $u1]
set b642 [base64 -mode decode $b641]
puts "$b2\n$o2\n$h2\n$u2\n$b642\n"
# end.

「package require」で指定するパッケージ名は「trf」ではなく「Trf」なので注意が必要です (TrfのpkgIndex.tclは正則の方法で生成されていないため)。 出力は、このようになります。

01001000011001010110110001101100011011110010110000100000011101000111\
00100110011000100000010101110110111101110010011011000110010000101110
110145154154157054040164162146040127157162154144056
48656C6C6F2C2074726620576F726C642E
2&5L;&\L('1R9B!7;W)L9"X~
SGVsbG8sIHRyZiBXb3JsZC4=


Hello, Trf World.
Hello, Trf World.
Hello, Trf World.
Hello, Trf World.
Hello, Trf World.

 uuencodeとBase64は、 もともと電子メールで画像などのバイナリデータを送信するときに、 (電子メールでは8ビット目をもつデータが送信できないため) すべてASCII文字からなるテキストに変換する目的で作られたコードで、 今でもuuencodeは主にUNIXで、Base64は主にMS-Windowsで使われています。 最近はメーラーが自動的に受送信時に変換・復元をやってくれることが多いので、 そんなの知らないという方も多いでしょうし、 このエンコードされたグチャグチャ(失礼)なテキストを見る機会もないわけですが、 メールボックスを見て直接何かするプログラムを作るなら役に立つかもしれません。 意外に興味深いのが「hex」で、 市販のアプリケーションソフトには簡単な暗号化というのでINIファイルに上の 「48656C6C6F2C2074726620576F726C642E」 のような文字が入っていることがままありますが、 これがデコードできるということで。 でも使い方としては特殊なので、これはそんなものだ、ということで。

●データの圧縮を行うコマンド

  • zip
  • bz2
はそれぞれgzip、bzip2というファイル圧縮プログラムと互換性のあるアルゴリズムで文字列の圧縮・復元を行うコマンドです。 使い方は簡単で、

# 圧縮
set result [zip -mode compress $source]
# 復元
set result [zip -mode decompress $source]

bz2も同様です。-levelオプションで「圧縮レベル」を指定することもできます。 これについては詳しくはgzipやbzip2のドキュメントを当るとよいでしょう。
 では簡単なファイル圧縮復元ツールを作ってみます。

#! /usr/local/bin/tclsh
package require Trf

proc decodeFile {infile a} {
    regsub "$a\$" $infile "" outfile
    if {[file exists $outfile]} {
	puts stderr "mm. $outfile already exists."; return
    }
    set fin  [open $infile r]
    set fout [open $outfile w]
    fconfigure $fin  -translation binary
    fconfigure $fout -translation binary
    set b [read $fin]
    close $fin
    if {$a == ".gz"} {
	set b2 [zip -mode decompress $b]
    } else {
	set b2 [bz2 -mode decompress $b]
    }
    puts -nonewline $fout $b2
    close $fout
}

proc encodeFile {infile a} {
    set outfile "$infile$a"
    if {[file exists $outfile]} {
	puts stderr "mm. $outfile already exists."; return
    }
    set fin  [open $infile r]
    set fout [open $outfile w]
    fconfigure $fin  -translation binary
    fconfigure $fout -translation binary
    set b [read $fin]
    close $fin
    if {$a == ".gz"} {
	set b2 [zip -mode compress $b]
    } else {
	set b2 [bz2 -mode compress $b]
    }
    puts -nonewline $fout $b2
    close $fout
}

if {"[set infile [lindex $argv 0]]" == ""} {
    puts stderr "usage: $argv0 infile"
}
set a [file extension $infile]
switch $a {
    .gz {  decodeFile $infile $a }
    .bz2 { decodeFile $infile $a }
    default {
        encodeFile $infile .gz
        encodeFile $infile .bz2
    }
}
# end.

 このようにファイルを圧縮・復元する場合には、readコマンドで中身を全部読み、 zipやbz2コマンドで変換してputsで書き出せばよいわけですが、 そのときfconfigureコマンドで -translation binaryを指定しないとバイナリデータが正しく扱われず、変な結果になります。
 このプログラムはgzipやbzip2プログラムで圧縮したファイルと互換性がないことに注意してください。 gzipプログラムは圧縮するときにファイルに関する情報をヘッダを出力の頭につけますが、 Trfのzipコマンドやbz2コマンドではこのヘッダを処理することができません。 したがって、gzipなどで圧縮したファイルに対し何かするのではなく、 独自のアプリケーションのデータを圧縮して保存する等の処理に使うのがよいでしょう。

●メッセージ・ダイジェストを行うコマンド

  • adler
  • crc
  • md5
インターネットでの通信において、 受信時のデータが元のデータに対して人為的またはその他のグレートなパワーによって改変や脱落が発生していないかを検証することは非常に大事なことであります。 メッセージ・ダイジェストはこのために使われるデータ処理で、 つまり大きなデータを適当に変換することによって、 ある種の簡単なテキストデータを作ります。 2つのデータの内容が全く同じ場合、変換して作ったメッセージ・ダイジェストも全く同じ内容になりますが、 両者の内容が少しでも異なる場合、 メッセージ・ダイジェストは全く異なる内容を生成します。

adler、crc、md5はいずれもこのメッセージ・ダイジェストを生成するコマンドで、 使い方も全く同じ、ただ生成するテキストの内容が違うだけです。 使い分け?聞かないでください。どれがどう優れているのか、 まったくわからないので、気に入ったのを使えばよいのかな? どこを基準に気に入るのかって?だから聞かないでください!! \+_+;/)

  set mdtext [adler $source]
そんなに長いテキストは用意できませんが、簡単なサンプルを下のように作ってみました。

#! /usr/local/bin/tclsh
package require Trf

set s1 {\
This is a joy in the world, joy on your mind, joy of your control.}
set s2 {\
This is a joy in the world, joy on your mind: joy of your control.}
set s3 {\
This is a joy in the world, joy on your mind, joy of your control.}
set ad1 [adler $s1]; set cr1 [crc   $s1]; set md1 [md5   $s1]
set ad2 [adler $s2]; set cr2 [crc   $s2]; set md2 [md5   $s2]
set ad3 [adler $s3]; set cr3 [crc   $s3]; set md3 [md5   $s3]
puts "$ad1\n$cr1\n$md1\n"
puts "$ad2\n$cr2\n$md2\n"
puts "$ad3\n$cr3\n$md3"
# end.

拡張レビュー分室 top
(first uploaded 2000/09/16 last updated 2010/09/19, MISUMI URANO - KENICHI USHIRODANI)