91

ファイルに何かを書き込んだ後、ファイルを削除しようとしていますFileOutputStream。これは私が書くために使用するコードです:

private void writeContent(File file, String fileContent) {
    FileOutputStream to;
    try {
        to = new FileOutputStream(file);
        to.write(fileContent.getBytes());
        to.flush();
        to.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

ご覧のとおり、ストリームをフラッシュして閉じますが、削除しようとするとfile.delete()false が返されます。

削除する前にファイルが存在するかどうかを確認したところfile.exists()、 、file.canRead()file.canWrite()file.canExecute()すべて true が返されました。これらのメソッドを呼び出した直後に、file.delete()false を返します。

私が間違ったことはありますか?

4

17 に答える 17

104

Java の別のバグ。私はめったにそれらを見つけることはなく、私の 10 年間のキャリアの中で 2 回目です。他の人が述べたように、これは私の解決策です。私はネザーを使用しSystem.gc()ました。しかし、ここで、私の場合、それは絶対に重要です。変?はい!

finally
{
    try
    {
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
        System.gc();
    }
    catch (IOException e)
    {
        logger.error(e.getMessage());
        e.printStackTrace();
    }
}
于 2010-11-18T09:18:32.783 に答える
49

うまくいったトリックはかなり奇妙でした。以前にファイルの内容を読んだことがあるので、を使用しBufferedReaderました。読んだ後、バッファを閉じました。

その間に切り替えて、今はを使用してコンテンツを読んでいますFileInputStream。また、読み終えたら、ストリームを閉じます。そして今、それは機能しています。

問題は、これについての説明がないことです。

私は知りませんし、互換性がありませんBufferedReaderFileOutputStream

于 2009-06-13T21:44:44.037 に答える
19

この簡単なことを試してみましたが、うまくいっているようです。

file.setWritable(true);
file.delete();

わたしにはできる。

これが機能しない場合は、Linux の場合は sudo で、Windows の場合は管理者として Java アプリケーションを実行してみてください。Javaにファイルのプロパティを変更する権限があることを確認するためだけです。

于 2011-05-22T19:46:45.283 に答える
6

ファイルを削除/名前変更する前に、すべてのリーダーまたはライター (例: BufferedReader/ InputStreamReader/ BufferedWriter) が適切に閉じられていることを確認する必要があります。

ファイルとの間でデータを読み書きしようとすると、ファイルはプロセスによって保持され、プログラムの実行が完了するまで解放されません。プログラムが終了する前に削除/名前変更操作を実行する場合は、クラスclose()に付属のメソッドを使用する必要があります。java.io.*

于 2014-02-27T09:30:40.683 に答える
3

Jon Skeet がコメントしたように、ファイルが常に閉じられるように、finally {...} ブロックでファイルを閉じる必要があります。そして、e.printStackTrace で例外を飲み込む代わりに、単純に例外をキャッチしてメソッド シグネチャに追加しないでください。何らかの理由でできない場合は、少なくとも次のようにします。

catch(IOException ex) {
    throw new RuntimeException("Error processing file XYZ", ex);
}

さて、質問番号#2:

これを行うとどうなりますか:

...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...

ファイルを削除していただけませんか?

また、ファイルは閉じられるときにフラッシュされます。私は IOUtils.closeQuietly(...) を使用しているので、flush メソッドを使用して、ファイルを閉じる前にファイルの内容がそこにあることを確認します (IOUtils.closeQuietly は例外をスローしません)。このようなもの:

...
try {
    ...
    to.flush();
} catch(IOException ex) {
    throw new CannotProcessFileException("whatever", ex);
} finally {
    IOUtils.closeQuietly(to);
}

したがって、ファイルの内容がそこにあることがわかります。ファイルを閉じることができるかどうかではなく、ファイルの内容が書き込まれることが通常私にとって重要であるため、ファイルが閉じられたかどうかは実際には問題ではありません。あなたの場合、重要なので、自分でファイルを閉じて、それに応じて例外を処理することをお勧めします。

于 2009-06-14T05:50:33.557 に答える
2

Eclipse IDE で作業している場合、アプリケーションの前回の起動時にファイルを閉じていない可能性があります。ファイルを削除しようとしたときに同じエラー メッセージが表示されたとき、それが原因でした。Eclipse IDE は、アプリケーションの終了後にすべてのファイルを閉じていないようです。

于 2013-04-04T13:36:20.823 に答える
1

うまくいけば、これは役に立ちます。Javaコードがコンテンツのコピーを他のフォルダーに作成した後、ファイルを削除できないという同様の問題に遭遇しました。大規模なグーグル検索の後、すべてのファイル操作関連の変数を明示的に宣言し、各ファイル操作オブジェクトの close() メソッドを呼び出して、それらを NULL に設定しました。次に、System.gc() と呼ばれる関数があり、ファイル i/o マッピングをクリアします (よくわかりません。Web サイトで何が与えられているかを教えてください)。

これが私のコード例です:

public void start() {
    File f = new File(this.archivePath + "\\" + this.currentFile.getName());
    this.Copy(this.currentFile, f);

    if(!this.currentFile.canWrite()){
        System.out.println("Write protected file " +
           this.currentFile.getAbsolutePath());

        return;
    }


    boolean ok = this.currentFile.delete();
    if(ok == false){
        System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
        return;
    }
}

private void Copy(File source, File dest) throws IOException {
    FileInputStream fin;
    FileOutputStream fout;
    FileChannel cin = null, cout = null;
    try {
        fin = new FileInputStream(source);
        cin = fin.getChannel();
        fout = new FileOutputStream(dest);
        cout = fout.getChannel();

        long size = cin.size();
        MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);

        cout.write(buf);
        buf.clear();
        buf = null;

        cin.close();
        cin = null;

        fin.close();
        fin = null;

        cout.close();
        cout = null;

        fout.close();
        fout = null;

        System.gc();

    } catch (Exception e){
        this.message = e.getMessage();
        e.printStackTrace();
    }
}
于 2009-11-10T08:24:08.827 に答える
0

ruby でかつて問題がありました。Windows のファイルは、ファイルを書き込んで閉じた後に実際に向きを変えて再読み込みできるようにするために「fsync」が必要でした。たぶん、これは同様の症状です (もしそうなら、本当に Windows のバグだと思います)。

于 2011-03-01T15:09:29.167 に答える
0

問題は、ファイルがまだプログラムによって開かれ、ロックされているように見えることです。または、それが開かれたプログラムのコンポーネントである可能性があるため、dispose()メソッドを使用してその問題を解決する必要があります。すなわちJFrame frame; .... frame.dispose();

于 2013-08-11T18:11:49.343 に答える
0

すべてのストリームを閉じるか、try-with-resource ブロックを使用する必要があります

static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException
{
    final String readLine;
    try (FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
            LineNumberReader lnr = new LineNumberReader(isr))
    {
        readLine = lnr.readLine();
    }
    return readLine;
}
于 2013-12-22T19:05:39.993 に答える
0

ここにリストされている解決策はどれも、私の状況では機能しませんでした。私の解決策は、while ループを使用してファイルを削除しようとすることでした。安全のために 5 秒 (構成可能) の制限があります。

File f = new File("/path/to/file");

int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
    synchronized(this){
        try {
            this.wait(250); //Wait for 250 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    limit--;
}

上記のループを使用すると、手動でガベージ コレクションを実行したり、ストリームを null に設定したりする必要がなくなりました。

于 2012-09-10T21:33:20.487 に答える
0

file.delete() が false を送信している場合、ほとんどの場合、Bufferedreader ハンドルは閉じられません。閉じるだけで、正常に機能するようです。

于 2014-02-03T08:48:26.790 に答える