miau's blog?

バイナリファイルの判定

今は保守っぽい仕事をやってるんですが、リリースのタイミングで更新のあったファイルだけをお客さんに送付することになっています。
そこで「ファイルの更新日時が特定の日時以降なら、そのファイルをコピーする」なんて Perl スクリプトを書いてます。

ところが、たまに「本番機の設定で送付しないといけないのに、開発機の設定のまま送付してしまう」なんてミスが起きてたので、NG-word 機能(ファイルに特定の文字 - 開発機の IP アドレスとか - が含まれていたら警告を表示する)を追加しました。
しばらくはちゃんと動作してたんですが、.xls や .png があると、警告が出まくることがわかりまして。

で、バイナリファイル検出方法で試行錯誤してたので、その対応の話。




とりあえず、最初にやった対策。
文字コードの判別に失敗したらバイナリファイルとみなす、というもの。

use Encode;
use Encode::Guess qw/euc-jp cp932 7bit-jis/;

my @files = <*>;

foreach my $file (@files) {
open IN, "<", $file or die "can't open $file: $!";
my $data = <IN>;
close IN;

my $enc = guess_encoding($data);
unless (ref($enc)) {
warn "no appropriate encoding\n";
next;
}
my $data = $enc->decode($data);

if ($data =~ /hoge/) {
warn qq/"hoge" found!\n/
}
}

(※実際は @files は File::Find 使ってますが、長くなるので省略)

でもこれだと .png が UTF-32BE として認識されて、チェックを抜けてしまうっぽく。

試しに
以前書いたアイテムと同じ方法で STDERR を取得
・エラーがあればバイナリファイルとみなす
なんて処理にしてみたんですが、これが結構重い。

ので、さらに別の方法。

if ($data =~ m/\p{Cn}/) {
warn "\p{Not_Assgined} found!\n";
next;
}

Unicode に該当しない文字がある場合はバイナリファイルとみなす、という処理。
普通に処理軽いし、今のところこの実装にしてます。

もっといい方法ご存知な方は教えてください・・・。


(2006/09/23 追記)

GIF ファイルが
・UTF-16BE
・UTF-16LE
・UTF-32BE
・UTF-32LE
あたりとみなさることがたまにあるっぽい。
鬱陶しいので guess_encoding() でこの辺りが出てきたらスキップすることに。
そうしてしまうとあまり意味ないような。
posted at 00:17:36 on 2005-10-20 by miau - Category: Perl No Trackbacks - Permalink

TrackBack

このエントリにトラックバックはありません
現在トラックバックは受け付けていません。

Comments

ma wrote:

拡張子で判別、っていう逃げはだめですか?
VSS6 は NULL があるかないかで判別してるらしいです。
2005-10-21 07:39:56

miau wrote:

拡張子で判別すると、予想外の拡張子が来たときに面倒なので、とりあえずその方法は無しで・・・。

あと、VSS6 の判別ってもっと複雑なことになってますよ、たぶん。
EUC-JP なファイルを時々バイナリファイルと誤認しますので。
2005-10-23 01:09:31

ma wrote:

SP で変わってるのかもしれないけど、 MS にこんなの載ってたよ。
http://www.microsoft.com/ja...
url=/japan/msdn/library/ja/guides/html/vstskHow_VSS_Treats_Binary_Files.asp

↑半角がどうとか言われたので改行入ってますが、連結して飛んでください
2005-10-23 07:11:40

miau wrote:

情報ありがとうございます。
msdn はたまに嘘載ってるので、今度実際の動作調べてみます。
2005-10-23 13:50:54

miau wrote:

追記したのでage
2006-09-23 18:38:05

Add Comments

現在コメントは受け付けていません。
お手数ですが、 こちら のコメント欄にでも記載していただければと思います。