• ベストアンサー

Java Zip回答時にxlsxが壊れる?

org.apache.tools.zip.ZipFileを使用しzipファイルの解凍を行っているのですが zipの内部にxlsxファイルが存在する場合、解凍したxlsxを開くと 下記のメッセージが表示されてしまいます。 xlsx解凍時には特別な処理等が必要なのでしょうか? メッセージ 「~には読み取れない内容が含まれています。このブックの内容を回復しますか?ブックの発行元が信頼できる場合は[はい]をクリックしてください。」 以上、よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

その現象とプログラムから、 ava = bis.available() 得た ava と、 bis.read(bs); でbsに読み込んだバイト数とに齟齬がある(読み込んだバイト数の方が1少ない)のではないだろうか、と予測します。 そこで、 InputStream.availavle のマニュアルを読みます。 http://docs.oracle.com/javase/jp/6/api/java/io/InputStream.html#available%28%29 > この入力ストリームのメソッドの次の呼び出しによって、ブロックせずにこの入力ストリームから読み込むことができる (またはスキップできる) 推定バイト数を返します。(略) 読み込むまたはスキップするバイト数が少なくなることがあります。 ということで、bs[ava]と確保したものを全て書き出すのは問題がありそうです。 と思って検索の続きを見ると、まったく同じ問題について書かれたブログが見付かりました。 > [Java]zipファイルの解凍ではまる(ファイル末尾にヌル文字が1バイトできる) http://daybreaksnow.hatenablog.jp/entry/2013/10/23/163221 available は参考程度にして、readの戻り値で正確に何バイト読んだかを求めて、writeでも正確にそのバイト数だけ書きだすのがよいようです。

geregerejp
質問者

お礼

回答ありがとうございます。 上記HPを参照しコードを修正することで解決いたしました。 他の方も回答ありがとうございました。

その他の回答 (3)

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.3

#1です。 #2さんも、小生も「Zip圧縮前のxlsxを確認するところからでしょ」と申しあげてます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

実行環境もプログラムも無しに正確な判断はできません。 ありがちな物で予想するなら、xlsxをASCIIモードで書き出している、というあたりが疑われます。 まず、元のzipが正しいかどうか確認するために。 (1)元のxlsxが正常に読めるか、Excelで開いて確認する。(保存終了すると内容が変わってしまうので、保存はしないで閉じる) (2)他のZIPツールで解凍する。 (3)(2)で解凍したxlsxと。圧縮元のxlsxが等しいか確認する。(バイナリーファイル比較ツールを使う) 以上で、ZIP自体に問題が無い、と確認できたら (4)あなたのプログラムで解凍したxlsx と、元のxlsxが等しいか確認する。(バイナリーファイル比較ツールを使う) (4)で比較した内容によって ・先頭とか末尾とかが増えている→余計なものまで出力してしまっている ・0x0Aや0x0Dが増えたり減ったりしている→ ASCIIモードでの書き出し。あるいは、改行付きでの書き出し ・ぜんぜん違う→根本的に何か間違えている とかが考えられます

geregerejp
質問者

補足

環境等提示せずに質問したにも関わらず、丁寧な回答ありがとうございます。 環境 java1.7 バイナリ比較ツールで比較した結果は 解凍後のファイルの末尾に「00」が常についておりました。 コードは以下になります。 何か問題がありますでしょうか? /** * Zipファイル解凍 * * @param String 解凍するファイルパス * @param String 解凍ファイル格納フォルダパス * @param boolean すでに解凍フォルダパスが存在した場合中身を空にするか trueで消す。 * @return List 解凍後出力パスファイルのリスト */ public List<String> decompressionZipFile(String inputPath, String outputPath,boolean outPutPathDellFlg) throws Exception{ org.apache.tools.zip.ZipFile zipFile = new org.apache.tools.zip.ZipFile(inputPath,"MS932"); File decoPath = new File(outputPath); ArrayList<String> returnList = new ArrayList<String>(); if(!decoPath.isDirectory()){ //作成 decoPath.mkdir(); }else{ if(outPutPathDellFlg){ //中身削除する。 delFolderAllFile(outputPath); } } Enumeration<? extends org.apache.tools.zip.ZipEntry> entries = zipFile.getEntries(); while (entries.hasMoreElements()) { org.apache.tools.zip.ZipEntry ze = entries.nextElement(); //出力先ファイル File outFile = new File(decoPath, ze.getName()); if (ze.isDirectory()) { outFile.mkdirs(); } else { returnList.add(outFile.getPath()); BufferedInputStream bis = null; BufferedOutputStream bos = null; InputStream is = zipFile.getInputStream(ze); bis = new BufferedInputStream(is); if (!outFile.getParentFile().exists()) { // ディレクトリ作成 outFile.getParentFile().mkdirs(); } // 出力先OutputStreamを作成。 bos = new BufferedOutputStream(new FileOutputStream(outFile)); //書込 int ava; while ((ava = bis.available()) > 0) { byte[] bs = new byte[ava]; // 入力 bis.read(bs); // 出力 bos.write(bs); } bos.flush(); bis.close(); bos.close(); } } zipFile.close(); return returnList; }

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

御自身でzip化した? 他の方からメールでもらったのなら、作成元で解凍テストしてもらう。 なんだか、NWドライブ越しのトラブルを持ったファイルに見えます。

関連するQ&A