出産前後の痔にはご注意!

通し番号や、日付などを数字で書く場合、
100
101
なら、まだいいのですが、
100000000000
100000000001
と続き、更に、桁が大きくなると、携帯電話などで見る場合パケットが気になります。
そこで、文字を圧縮する原理を利用して、簡単に圧縮できないでしょうか?

例えば
100000000000
左(L)から1が(g)1つで(d)0が(g)8つ
L1g1d0g11
こうすると、短くないますよね。
バイナリレベルで上手に圧縮するともっと、短く正確にできるのではないかと思っています。

他にも、探して、下記のようなものも見つけたのですが、圧縮されたものを、print出力してみると、文字化けしていて使えそうにありませんでした。
何か、良い方法は無いでしょうか?
また、数字以外の文字が混じった場合でも対応できれば、更に助かります。
宜しくお願い致します。

use Compress::Zlib;
$num = compress($num);
$num = uncompress($num);

このQ&Aに関連する最新のQ&A

A 回答 (1件)

圧縮のアルゴリズムは、たくさんあります。


どれを選ぶか、もしくは組み合わせるかの問題かと思います。

メジャーなところで、zipなどの圧縮を行い、base64等の符号化処理をするのが
良いのではないでしょうか。

テキストor非テキストの文字列
 ↓
ZIPアルゴリズムで圧縮(縮める)
 ↓
非テキストの文字列
 ↓
base64符号化(問題ある制御符号を無くすためちょっと伸ばす)
 ↓
テキスト文字列(7ビット文字だけの組み合わせ文字列)


ただし、アルゴリズムや符号化の方式を選び間違うと、
元の文字列より長くなることがあるので、注意してください。

例えば、256バイト以下の対象データをLZHアルゴリズムで圧縮すると、
256バイト以上の圧縮結果となります。
また、符号化方式も、識別のため前後にマジックワードが付与されたり
するので、対象データが短すぎると、大元の対象データより長くなる可能性も
あります。

なお、当然ですが、復元するのに仕組みが必要になるので、相手が携帯であれば
携帯側に、javaなどで復元処理を実装することになると思いますので、メジャーなものを
組み合わせれば、復元側も既存のモノを流用できて良いと思います。

この回答への補足

回答いただきありがとうございます。
perl入門者ですので、とりあえず、分かる範囲内でやってみました。

use Compress::Zlib;

$num = compress($num);
print $num;
print "\n<br>";

use MIME::Base64 ();
$num = MIME::Base64::encode($num);

print $num;
print "\n<br>";

$num = MIME::Base64::decode($num);

print $num;
print "\n<br>";

$num = uncompress($num);
print $num;
print "\n<br>";

としてみたのですが、
100文字を、75文字程度にすることができました。
もう少し、圧縮率を上げることはできないものでしょうかね?
また、”+=/”を含まないA-Za-z0-9のみで、Base64のような方法は無いものでしょうかね?

また、全て、サーバー側で処理して行うため(今回は、URLのみの短縮を目的)、個人の方が作成されている手法でも良いのですが、何か、良いものは無いでしょうかね?
ご存知でしたら、教えてください。
宜しくお願い致します。

補足日時:2006/01/21 16:53
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Q文字コードの変換(Shift-JISからUTF8)

文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに
プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを
確認するとShift-JISのままです。
どなたか教えていただけないでしょうか?
ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。

#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Encode;

my $input_file="input.csv";
my $output_file="output.txt";
open (IN, $input_file) or die "$!";
open (OUT, ">$output_file") or die "$!";

while (<IN>){
chomp ($_);
my @data=split(/,/,$_);

for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}
print OUT "\n";
}
close (IN);
close (OUT);

文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに
プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを
確認するとShift-JISのままです。
どなたか教えていただけないでしょうか?
ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。

#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Encode;

my $input_file="input.csv";
my $output_file="output.txt";
open (IN, $input_file) or die "$!...続きを読む

Aベストアンサー

あの、私のや他の回答をよく読んで考えてください。


for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}

この部分は **** $_には何の影響も与えません ****
よって、** 出力に関することだけに注目したら **

for(my $i=0;$i<@data;$i++){
print OUT $_;
}

これと等価です。どこで「Shift_JIS からUTF-8へ変換」してますか?
$_は「while (<IN>){」の<IN>で1行読み込まれ、「chomp ($_);」で末尾の改行コードが削除されただけで、移行なにも変化していません。コードは入力のまま=Shift_JISです。それをそのまま出力すればShift_JISになるのが正解です。
しかも、項目数分だけ繰り返し出力されます。
(重複行になる、と#1に書いたのはchompのことを失念していた私のミスです)

@dataを変更したのなら、出力するのは@dataでしょう。
join(",", @data)とすれば、項目をカンマ区切りの文字列にすることができます。


あと#2にあったfrom_toの使い方。マニュアルをよく読みましょう
http://perldoc.perl.org/Encode.html#[$length-=]-from_to($octets,-FROM_ENC,-TO_ENC-[,-CHECK])
・$octetsを直接変換する
・$octetsの長さを返す
とあります。つまり
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8')
だと,$data[$i]には元の内容は破棄されて、文字列の長さになってしまいます。



各項目毎に処理したい、という意図はわかりました。

ですが、文字コードの変換が項目毎に違うなんてことはまず無いでしょう。
それならば、$_で1行をコード変換→splitして項目毎の処理、としてもいいのでは?

ついでにPerlIOを使って
open (IN, "<:encoding(shift_jis)", $input_file) or die "$!";
open (OUT, ">:utf8", $output_file) or die "$!";
とでもやれば、プログラム中はコードをあまり意識せずに文字列処理ができます。

あの、私のや他の回答をよく読んで考えてください。


for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}

この部分は **** $_には何の影響も与えません ****
よって、** 出力に関することだけに注目したら **

for(my $i=0;$i<@data;$i++){
print OUT $_;
}

これと等価です。どこで「Shift_JIS からUTF-8へ変換」してますか?
$_は「while (<IN>){」の<IN>で1行読み込まれ、「chomp ($_);」で末尾の改行コ...続きを読む


人気Q&Aランキング