雑記帳 2006年 7月第6週

2006/07/30 Sun.

ところで、改行無しで横に長ったらしいファイルとか手元に来ると、はっきり言って読む気すら消えうせる。でも読まないと。
いちいち手動で改行を入れていくのもアホらしいし、とりあえずPerlで簡単なスクリプトを組むかってことで書いてみた。

use strict;
require "jcode.pl";
my $ascii = '[\x00-\x7F]';
my $twoBytes = '[\x8E\xA1-\xFE][\xA1-\xFE]';
my $threeBytes = '\x8F[\xA1-\xFE][\xA1-\xFE]';
my @files = ();
foreach my $file (@files) {
    open (FILE, "<$file");
    my @lines = <FILE>;
    close (FILE);
    my @new = ();
    foreach (@lines) {
        $_ =~ s/\x0D\x0A|\x0D|\x0A/\n/g;
        chomp ($_);
        if ($_ eq "") {
            push (@new, "\n");
            next;
        }
        &jcode::convert (\$_, "euc", "sjis");
        my @chars = $_ =~ /($ascii|$twoBytes|$threeBytes)/og;
        if (length (join ("", @chars)) > 180) {
            my @temp;
            my $temp_char;
            foreach (@chars) {
                $temp_char .= $_;
                if (length ($temp_char) > 180) {
                    push (@temp, $temp_char);
                    $temp_char = "";
                }
            }
            if ($temp_char ne "") {
                push (@temp, $temp_char);
            }
            foreach (@temp) {
                &jcode::convert (\$_, "sjis", "euc");
                push (@new, $_ . "\n");
            }
        } else {
            &jcode::convert (\$_, "sjis", "euc");
            push (@new, $_ . "\n");
        }
    }
    my $new_file = (split (/\./, $file))[0] . "_new.txt";
    open (FILE2, ">$new_file");
    print FILE2 @new;
    close (FILE2);
}

これを実行すると、ファイルの1行の長さが180バイトから182バイトにまで切り詰められて、改行も入って見やすくなる。
あ、これはWindows上でしか動かすつもりないし、一回実行したら終了させるだけなので、コーディングは激しく適当だったり。
職場のマシンのデスクトップ解像度は1400x1050だけど、これでも横幅が足りないと思わせるようなファイルを普通作るか?
んで、例えばこの方法で1行を180バイトから182バイトにまで切り詰めたファイルをブラウザに放り込んで読むのが自分流。
エディタはあくまでもエディタとして利用しているワケで、普通のテキストドキュメントを読むのには適さない配色になってる。
ただ、この方法でファイルを作り直しても、ブラウザに放り込む際にファイルサイズが大きいとブラウザの動作が重くなりやすい。
今度は、このファイルを指定したサイズごとに複数のファイルに分割してみる。下のソースの例だと64KBごとに分割になるか。

use strict;
my @files = ();
foreach my $file (@files) {
    open (FILE, "<$file");
    my @data = <FILE>;
    close (FILE);
    my $data_line = "";
    my $count = 0;
    my $count_new;
    foreach (@data) {
        if (length ($data_line) < 1024 * 64) {
            $data_line .= $_;
            next;
        }
        $count_new = sprintf ("%02d", $count);
        my $new_file = (split (/\./, $file))[0] . $count_new . ".txt";
        open (NEW, ">$new_file");
        print NEW $data_line . $_;
        close (NEW);
        $data_line = "";
        $count++;
    }
    if ($data_line ne "") {
        $count_new = sprintf ("%02d", $count);
        my $new_file = (split (/\./, $file))[0] . $count_new . ".txt";
        open (NEW, ">$new_file");
        print NEW $data_line;
        close (NEW);
    }
}

何で職場のマシンは大きめのサイズのテキストファイルをブラウザに突っ込むと重くなるんだ?メモリは結構あるのに。
作業中にファイル開こうとしてそのままマシンが固まったりすると、仕掛りの作業にも影響が出るしダメージが大きい。
いちいち作業対象のファイルにまで手を下してマシンが固まらんようにとの防止策を採らねばならんとは、アホな話ですわ。

ソース書いてて思ったけど、Perlの場合は変数展開が不要な場合の文字列は全て「'」で囲うようにした方がいいのかな。
HTMLにソースを落とす際にいちいち「"」を「&quot;」とかの実態参照に置き換えるのもメンドいし、可読性の問題がある。
Javaならchar型でもない限り、普通のString型なら「"」しか使えないけど、Perlはある意味この適当さが優秀なんだよな。

2006/07/31 Mon.

突然ですが、自分の携帯は「V603SH」です。外部メモリとしてSDカードが使え、SDローカルコンテンツってのが作れる。
例えば、モバイル用のHTMLを作成した場合などにそのコンテンツをSDカードに入れれば、動作確認ができるというワケ。
さて、巨大なテキストファイルをブラウザで快適に読むために、あれこれ試行錯誤をしたソースは既に書いた通りです。
しかしながら、ブラウザを使うということは自宅やら職場にいるワケであって、他にもやるべきことは色々あるのです。
そんなワケで、巨大なテキストファイルをSDカードに設定しておけば、携帯でも快適に読めるんじゃないかと思ったり。

まず実験したのが、テキストファイルをそのままSDカードのデータ用フォルダに突っ込み、表示させてみること。
やはりメモリ上にて展開できるサイズが決まっているらしく、ファイルサイズは30KB以下にしろとの警告が出てきた。
しょうがないので、昨日の雑記に書いた二つ目のスクリプトを使って、余裕を見て25KBごとにファイルを分割する。
これで見事に展開できたのだが、困ったことにテキストファイルの画面スクロールが行単位でしかスクロールできない。
例えば500行あったとしたら、500回も↓キーを押さないと表示できないワケだ。ぶっちゃけ、激しくメンドくさい。
対象ファイルのHTML化はどうだ。HTML表示時は、画面単位でのスクロールかリンクが貼ってある箇所へのジャンプとなる。
当然、ただのテキストファイルをHTML化するだけだし、リンクがある箇所は存在せずに画面単位でのスクロールになるはず。
さて、HTMLは何KBまで表示できたっけか?実験するのがメンドいので、恐らく表示できるであろう10KBで分割してみる。

use strict;
my @files = ();
foreach my $file (@files) {
    open (FILE, "<$file");
    my @data = <FILE>;
    close (FILE);
    my $count = 0;
    my $count_new;
    my $data_line = "<HTML>\n<HEAD>\n<TITLE>";
    $data_line .= (split (/\./, $file))[0] . sprintf ("%03d", $count);
    $data_line .= "</TITLE>\n</HEAD>\n<BODY>\n";
    my @new_file_list = ();
    foreach (@data) {
        chomp ($_);
        if (length ($data_line) < 1024 * 10) {
            $data_line .= $_ . "<BR>\n";
            next;
        }
        $count_new = sprintf ("%03d", $count);
        my $new_file = (split (/\./, $file))[0] . $count_new . ".html";
        open (NEW, ">$new_file");
        print NEW $data_line . $_ . "<BR>\n</BODY>\n</HTML>\n";
        close (NEW);
        push (@new_file_list, $new_file);
        $count++;
        $data_line = "<HTML>\n<HEAD>\n<TITLE>";
        $data_line .= (split (/\./, $file))[0] . sprintf ("%03d", $count);
        $data_line .= "</TITLE>\n</HEAD>\n<BODY>\n";
    }
    if ($data_line ne "") {
        $count_new = sprintf ("%03d", $count);
        my $new_file = (split (/\./, $file))[0] . $count_new . ".html";
        open (NEW, ">$new_file");
        print NEW $data_line . "<BR>\n</BODY>\n</HTML>\n";
        close (NEW);
        push (@new_file_list, $new_file);
    }
    my $indexfile = (split (/\./, $file))[0] . ".html";
    open (HTML, ">$indexfile");
    print HTML "<HTML>\n<HEAD>\n<TITLE>";
    print HTML (split (/\./, $file))[0];
    print HTML "</TITLE>\n</HEAD>\n<BODY>\n";
    foreach my $filelist (@new_file_list) {
        my $linkfile = (split (/\./, $filelist))[0];
        print HTML "<A href=\"$filelist\">$linkfile</A><BR>\n";
    }
    print HTML "</BODY></HTML>\n";
    close (HTML);
}

これで10KBごとにHTML化して分割した個別のファイルと、そのファイルにリンクを貼った「対象ファイル名.html」が完成。
あとは「index.html」に「対象ファイル名.html」へのリンクを貼ったHTMLを書いて、SDカードのローカルコンテンツに設定。
SDカード内の「PRIVATE」「SDJPHONE」「SDコンテンツ」の階層の下にフォルダを作って、その下に「index.html」を放り込む。
こうすることで、テキストだったものがHTMLとして表示されるので、スクロールも画面単位になって快適に見られるワケだ。
実は上記スクリプトには微妙に納得いかない部分があるんだけど、これも頻繁に使うワケではないので放置しておこうか。
わざと冗長な書き方をしてる部分があるけど、ウチはSXGAを対象にしてるんで、あまり一行の横幅を長くできないのよね。

で、SDカードでのローカルコンテンツの設定方法について参照したサイトは「こちら」。サイト名はどうも微妙なので省略。
SDローカルコンテンツ系のサイトがもう一つあったんだけど、ちょっとリンクを貼るのは躊躇するようなトコなので却下。