- PR -

zipファイルを文字化けせずに作る方法

投稿者投稿内容
onoke
会議室デビュー日: 2003/08/08
投稿数: 4
投稿日時: 2003-08-08 16:49
初めて投稿させて頂きます。どうぞよろしくお願いいたします。
a.htm,b.htmと、複数のテキストファイルをzip化するために
下記の様なテストプログラムを作成しましたが、zipを解凍する
と各htmファイルの日本語が文字化けしてしまいました。
これは、ZipOutputStreamでキャラクタ指定していないためだ
と思われるのですが、さてputNextEntryを生かしながら文字化け
しない様にzip化するにはどうしたらいいのでしょう?
−-----------------------
import java.io.*;
import java.util.*;
import java.util.zip.*;

public class ZipTest{
public static void main( String[] args ){
try{
FileOutputStream f = new FileOutputStream( "ziptest.zip" );
ZipOutputStream z = new ZipOutputStream( f );
FileInputStream fin = null;
BufferedReader in = null;
for( int i=0; i<args.length; i++ ){
System.out.println( "Writing file " + args[i] );
fin = new FileInputStream( args[i] );
in = new BufferedReader( new InputStreamReader( fin, "SJIS" ));
z.putNextEntry( new ZipEntry( args[i] ) );
int c;
while((c=in.read()) != -1 ){
z.write( c );
}

in.close();
}

z.close();
f.close();
}catch( Exception e ){
e.printStackTrace();
}
}
}
_________________
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-08-08 17:41
引用:
onokeさんの書き込み (2003-08-08 16:49) より:

これは、ZipOutputStreamでキャラクタ指定していないためだと思われるのですが、

ちがいます。問題点は
引用:
onokeさんの書き込み (2003-08-08 16:49) より:

while((c=in.read()) != -1 ){ //readerから 1文字(char1個)読み込み
 z.write( c ); //OutputStream に1バイト(byte1個)書き込み
}

としている事です。単純に in.read() を fin.read() に置き換え、in (Reader)に関する記述を全て削除すれば文字化けの件に関しては解決すると思います。
onoke
会議室デビュー日: 2003/08/08
投稿数: 4
投稿日時: 2003-08-08 22:09
おかげさまで解決しました。
ありがとうございました。
_________________
R-55
常連さん
会議室デビュー日: 2003/03/13
投稿数: 29
投稿日時: 2003-08-11 09:49
こんにちは、R-55です。

確認させていただきたいのですが

in = new BufferedReader( new InputStreamReader( fin, "SJIS" ));

の部分でSJISとして読み込み、unicodeに変換後そのまま書き出しているので
文字化けしているという解釈でよろしいのでしょうか。

内部でどのような処理がなされて文字化けしているのかわかれば
BufferedReaderを使用しても文字化けしないように出来るのかと思い、
(もちろん一般的な方法ではないのでしょうが)
SJISの部分を書き換えたりして試してみたのですがうまくいきませんでした。

文字コードに関する知識が浅く、非常に的外れなことを言っているのだと
思うのですがそんなことができるならぜひ知りたいのでご教授いただければ
と思います。
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-08-11 21:47
引用:
R-55さんの書き込み (2003-08-11 09:49) より:

in = new BufferedReader( new InputStreamReader( fin, "SJIS" ));

の部分でSJISとして読み込み、unicodeに変換後そのまま書き出しているので文字化けしているという解釈でよろしいのでしょうか。

「そのまま書き出している」のであれば SJIS から unicode への変換が行われただけで、unicode が読めるエディタ等で開けば見れるはずですが、「そのまま書き出していない」ので文字化けの原因となっています。

引用:
R-55さんの書き込み (2003-08-11 09:49) より:

SJISの部分を書き換えたりして試してみたのですがうまくいきませんでした。

ISO-8859-1は お試しになりましたか?
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-08-12 09:41
これはバイトストリームと文字ストリームの違いですね。
APIのjava.io.Reader#read()とjava.io.OutputStream.write(int)の記述を見れば、そのまま書き出されないことがわかると思います。
ISO-8859-1を指定すれば、(Unicodeでの出力は)結果的に上手くいくと思いますが、本質的な解決法ではないでしょう。
バッファリングしたいのであれば、BufferedInputStreamを使うべきです。

#追記
onokeさんへ、ストリームのcloseはfinally句に書くようにしてください。

[ メッセージ編集済み 編集者: Wata 編集日時 2003-08-12 09:45 ]
R-55
常連さん
会議室デビュー日: 2003/03/13
投稿数: 29
投稿日時: 2003-08-12 10:02
こんにちはR-55です。

引用:
お犬様さんの書き込み( 2003-08-11 21:47)より

ISO-8859-1は お試しになりましたか?



すいません、てっきり忘れてました。試してみたらうまくいきました。
ISO-8859-1はバイト単位で扱うから結果的にうまくいくということでしょうか。

引用:
Wataさんの書き込み( 2003-08-12 09:41)より

APIのjava.io.Reader#read()とjava.io.OutputStream.write(int)の記述を見れば、そのまま書き出されないことがわかると思います。



お犬様さん(なんか変?)も最初に指摘してくださっていたのに気付かず
基本的な調査が足りませんでした。
java.io.OutputStream.write(int)では上位 24 ビットは無視され、
下位 8 ビットのみ書き込まれるということですね。
その後バイナリエディタで確認したところやはり2バイト文字は全て
1バイトに切り捨てられていました。

あと恥を忍んで書きますと2バイト文字が書き出されるとき
上位バイトと下位バイトが入れ替わっているみたいなのですが、
日(65 E5) 本(67 2C) 語(8A 9E)が
E5 65 , 2C 67 , 9E 8A のようになるのも知りませんでした。

大変勉強になりました、ありがとうございます。

[ メッセージ編集済み 編集者: R-55 編集日時 2003-08-12 10:03 ]
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-08-12 18:07
引用:
R-55さんの書き込み (2003-08-12 10:02) より:

あと恥を忍んで書きますと2バイト文字が書き出されるとき上位バイトと下位バイトが入れ替わっているみたいなのですが、日(65 E5) 本(67 2C) 語(8A 9E)が E5 65 , 2C 67 , 9E 8A のようになるのも知りませんでした。

単に UTF-16LE で出力なさっているだけだと思います。UTF-16BE と指定すれば上位バイトと下位バイトが入れ替わる事は無いと思います。

[ メッセージ編集済み 編集者: お犬様 編集日時 2003-08-12 18:12 ]

スキルアップ/キャリアアップ(JOB@IT)