Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

zipファイルを含むzipファイルの解凍(2)

前回の質問:
http://www.javaroad.jp/bbs/answer.jsp?q_id=200710022008452

-------------------------------------------------------------

前回に引き続き新たな問題です…。

前回のソースでzipファイルを展開後、ファイルを削除するメソッドを追加しました。(一時ファイルのような扱いにしたかったため)
しかし、ファイルによっては削除できないものが出てきました。
アプリケーション起動中にエクスプローラから削除しようとしてもできませんでした。
終了後は問題なく削除できたため、このアプリケーション中でファイルを開いているようです。
zip展開メソッドではきちんとStream#close()で後片付けしたのですが…。

削除メソッドでdelete()==falseの場合にdeleteOnExit()をセットしましたが、アプリケーションを終了しても削除されていませんでした。
同じスレッド中でファイル転送をしているので、同期の問題かと思いましたが、ファイル転送終了後もエクスプローラからの削除はできませんでした。

どなたか原因について怪しいと思われる箇所がお分かりの方、ご教授よろしくお願い致します。


------------------- *以下ソース* -------------------
private String firmwarePackge = "firmware.zip";

private File[] extractionZip() throws Exception
    {
      setLog("zipファイルを展開します :" + firmwarePackage);
      // 解凍後のファイルサイズのデフォルト値
      // 取り合えず 10MB 確保しておけば十分のはず
      final int SIZE = 10000000;
      final String DIR_TEMP = "temp";
      Vector tmpFiles = new Vector();

      // *** check File-exist ***
      if (!controller.checkFileExists(firmwarePackage)) {
        throw new FileNotFoundException(firmwarePackage + " is not Found.");
      }
      // *** check File-type ***
      new ZipFile(firmwarePackage);

      ZipInputStream zis = new ZipInputStream(new FileInputStream(firmwarePackage));
      ZipEntry zent = null;
      BufferedInputStream bis = null;

      // アーカイブ中に含まれるファイル情報の取得
      while ((zent = zis.getNextEntry()) != null) {
        String fileName = zent.getName();
        File tempDir = new File(DIR_TEMP);
        String tempDirPath = tempDir.getAbsolutePath();
        tempDir.mkdir();

        // フォルダ
        int separator = fileName.lastIndexOf("/");
        if (separator != -1) {
          String dir = fileName.substring(0, separator);
          //   fileName = fileName.substring(separator + 1);
          File file = new File(tempDirPath + File.separator + dir);
          if (!file.exists()) {
            file.mkdir();
          }
        }

        // バイト配列を確保
        byte[] buf = new byte[SIZE];
        bis = new BufferedInputStream(zis);

        // 展開ファイルを読み出す
        int realSize = bis.read(buf, 0, SIZE);

        // currentにファイルを書き出す。
    String unZipRoot = tempDirPath + File.separator + fileName;
        FileOutputStream fos = new FileOutputStream(unZipRoot);
        fos.write(buf, 0, realSize);

        // あとかたづけ
        fos.close();
        zis.closeEntry();
        File developedFile = new File(unZipRoot);
      }

      // あとかたづけ・その2
      bis.close();
      zis.close();

    }

/**
 * 削除 : 引数path以下のファイル・ディレクトリを削除する。
 */
private void deleteTempFiles(String path) //throws IOException
    {
      File file = new File(path);
      File[] list = file.listFiles();
      boolean isDir = false;
      for (int i = 0; i < list.length; i++) {
        if (list[i].isDirectory()) {
          deleteTempFiles(list[i].getAbsolutePath());
          if (!list[i].delete()) {
            System.out.println("Cannot delet file :" + list[i].getName());
            list[i].deleteOnExit();
          }
        }
        else {
          if (!list[i].delete()) {
            System.out.println("Cannot delet file :" + list[i].getName());
            list[i].deleteOnExit();
          }
        }
      }
    }

7

回答

4964

閲覧

7件の回答

評価

0

ソースはちゃんと見ていないのですが・・
私はこのような場合、問題の切り分けを行いますね
1.削除メソッドだけ実行した場合うまくいくか
2.ファイル転送処理のみ行う物で削除出来るか
3.zip解凍後間に何もはさまずに削除の場合どうか
とか調べようはあると思います。

評価

0

tama様

ご回答ありがとうございます。
そうですね、まずは問題点がどこにあるのかをもう少し詳細に調べてみます。
基本中の基本ですね。お恥ずかしいです。

ありがとうございます。

評価

0

解決しました。

原因はやはりStreamがきちんと閉じられていないことでした。
ただし、zip展開メソッド中ではなく、ファイル転送の。。。

ファイル転送は別の人が作ったものを利用させてもらっていたんですが、その記述が以下↓

ftp.storeFile(remoteFile, new FileInputStream(localFile));

これを見た瞬間「…怪しすぎる」と思いました^^;
引数でnewして渡してあげれば、そのメソッドを抜けたときに
オブジェクト消滅するんじゃないかなぁと思ったんですが、
「とりあえず試してみよ!」ということで以下のように
明示的にして実行してみました↓

      FileInputStream fis = new FileInputStream(localFile);
      ftp.storeFile(remoteFile, fis);
      fis.close();

すると、なんときちんと転送後でもファイルが削除できました。
tama様が追求するようおっしゃってくださったおかげで、
私のような初心者でも自分で解決することができました!
本当にありがとうございます。


でも、引数でnewして渡したオブジェクトって、メソッド終わっても死なないこともあるんですね…。
調べてみょ。

評価

0

オブジェクトが消滅するのは、ガベージコレクションが発生したときですよ。
メソッドの終わりで消滅するのは、オブジェクトへの参照です。

評価

0

解決したみたいで良かったですね。
GCを過信というかちゃんと理解していないと起きるパターンですね。

評価

0

>mio様
そのようですね!
この場合もただ参照だけが消滅しただけで、生成したインスタンス自体はひっそり生き残っていたようです。
これでまたひとつ賢くなりました(^^)9
ありがとうございます。

>tama様
Javaの師匠に言われた「オブジェクトは生き物だからなぁ。」
という言葉が脳裏をよぎりました^^;
まだまだ正しく理解していない事柄がたくさんあるだろうから、これからも勉強がんばります!

ありがとうございました!

評価

0

>この場合もただ参照だけが消滅しただけで、生成したインスタンス自体はひっそり生き残っていたようです。
その理解は間違ってますよ。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。