Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Java - soubor nelze smazat

Dobrý den,

Potřeboval bych smazat soubory, co jsem si sám vytvořil. Ovšem nejde to. Dělám to pomocí tohohle kódu.

public void play() {
        number += 1;
        if (number < LIST_FILES.size()) {
            hit = new Media(new File(LIST_FILES.get(number).toString()).toURI().toString());
            setText(LIST_FILES.get(number).getName().substring(0, LIST_FILES.get(number).getName().lastIndexOf(".")));
            media_player = new MediaPlayer(hit);
            media_player.setOnEndOfMedia(() -> play());
            media_player.play();
        } else {
            for (File file: LIST_FILES)
               if (file.getName().endsWith("wav")) {
                    System.out.println(file.delete());
                }
            LIST_FILES.clear();
            choose_song();
        }
    }

Metoda file.delete() funguje čistě náhodně, někdy se nesmaže nic a nebo se smaže pouze pár souborů.

Když jsem však použil metodu Files.delete(file.toPath()), tak to vyhodilo hlášku, že soubor nelze smazat, protože je využíván jiným procesem.

Jenže vůbec nevím který.

Prosím o radu

Předem děkuji.

Předmět Autor Datum
skús po vytvorení súboru zatvoriť output stream
fihsafdliuashfo 17.08.2017 19:26
fihsafdliuashfo
Ale v té metodě se to vždy zavře. public boolean decode(String inFileName, String outFileName) thro…
MichalDM 17.08.2017 19:41
MichalDM
Pravdepodobne je ten súbor používaný tvojím vlastným procesom. Myslím, že MediaPlayer mal taký bug,…
moose 20.08.2017 03:48
moose
Nešlo mě to smazat, tak jsem to dočasně odložil. Teď jsem se však k tomu znova vrátil. Ve windows j…
MichalDM 01.11.2017 23:04
MichalDM
Veď moose ti to už celé vysvetlil, že lepšie to snáď ani vysvetliť nejde, tak aký máš vlastne problé…
los 01.11.2017 23:54
los
Ano. To jsem četl v době napsání. Ale jak jsem řekl Files.delete(file.toPath()); pouze vyhodí hlášku…
MichalDM 02.11.2017 18:13
MichalDM
Tak už jsem to vyřešil. File má metodu deleteOnExit(), což je ideální, protože právě po zastavení pr…
MichalDM 03.11.2017 16:37
MichalDM
Pokud jsou ty soubory jen docasne (po cas behu aplikace), tak nechapu proc nepouzijes tempfile...
MaSo 03.11.2017 17:27
MaSo
Tohle nejsou žádné dočasné soubory, takže to použít nemůžu. Každopádně jsem se ptal na něco jiného,…
MichalDM 03.11.2017 17:41
MichalDM
deleteOnExit() funguje dobře, sice tam dochází ke zpoždění smazání, ale to nevadí. Jenže jsem chtěl…
MichalDM 03.11.2017 23:24
MichalDM
Tak smazání funguje s deleteOnExit(); bez problému. (I když jsem volání garbage collector smazal).… poslední
MichalDM 07.11.2017 16:36
MichalDM

Ale v té metodě se to vždy zavře.

public boolean decode(String inFileName, String outFileName) throws IOException {
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(inFileName);
            os = new FileOutputStream(outFileName);
            wav = new WavWriter(os);
            FLACDecoder decoder = new FLACDecoder(is);
            decoder.addPCMProcessor(this);
            decoder.decode();
        } catch (IOException e) {
             return false;
        } finally {
            if (is != null) {
                is.close();
            }
            if (os != null) {
                os.close();
            }
        }
        return true;
    }

Pravdepodobne je ten súbor používaný tvojím vlastným procesom. Myslím, že MediaPlayer mal taký bug, že neuvoľnil handle na súbor, neviem či s tým niečo spravili. Kto drží otvorený handle môžeš zistiť použitím programu handle.exe.

MediaPlayer má metódu dispose, ktorá zaručene zatvorí všetky prostriedky, ktoré používa. Nevýhodou je, že ho už potom nemôžeš použiť, takže si v prípade potreby musíš vytvoriť novú inštanciu. Ale vidím, že novú inštanciu vytváraš vždy, takže ti to asi môže byť jedno.

Ešte pár menej podstatných až nepodstatných pripomienok ku kódu:
- skús viac používať premenné, LIST_FILES.get(number).getName() tam máš 2x v jednom riadku, ktorý je potom zbytočne dlhý
- používaj try-with-resources, ak môžeš (a keďže si skúšal Files.delete, tak môžeš, lebo máš k dispozícii minimálne Javu 7) - výrazne tým zjednodušíš kód
- na tvojom mieste by som uprednostnil Files.deleteIfExists pred file.delete - file.delete v prípade zlyhania len vráti false a ak to explicitne neskontroluješ, tak sa nedozvieš, že vznikol problém
- pomenúvaj premenné podľa javovej konvencie, t.j. žiadne podčiarniky v názvoch premenných, ale camelCase

Nešlo mě to smazat, tak jsem to dočasně odložil. Teď jsem se však k tomu znova vrátil.

Ve windows jsem zapnul Resource Monitor a tam zjistil, že nesmazatelné soubory jsou držené samotnou javou.

Když ji ukončím, tak se vypne celý program.

Nevíte, prosím vás, co s tím?

Děkuji.

Ano. To jsem četl v době napsání. Ale jak jsem řekl Files.delete(file.toPath()); pouze vyhodí hlášku.

Proces nemá přístup k souboru, neboť jej právě využívá jiný proces.

A Resource Monitor řekl, že ho využívá samotný puštěný projekt. Což nahrává tomu i fakt, že po ukončení běžícího projektu jdou soubory bez problému smazat.

media_player.dispose();
Runtime.getRuntime().gc();

Jenže i když zavolám dispose() a uměle vyvolám garbage collector, přesto se občas stane, že soubor/y nejdou smazat.

Tak už jsem to vyřešil. File má metodu deleteOnExit(), což je ideální, protože právě po zastavení projektu šly všechny soubory smazat.

Nicméně Runtime.getRuntime().gc(); musím zavolat i tak (mediaPlayer.dispose() nemá žádný vliv, takže je zbytečné ho tam psát).

Jelikož však jsou vytvořené soubory do ukončení projektu viditelné, tak bych se chtěl zeptat jak, prosím vás, nastavit soubor jako skrytý.

Děkuji.

deleteOnExit() funguje dobře, sice tam dochází ke zpoždění smazání, ale to nevadí.

Jenže jsem chtěl nastavit vytvořené soubory skryté.

Přímo v konstruktoru nastavím Runtime.getRuntime().exec("attrib +h " + getPath());

To funguje dobře, ale pouze od 2. souboru. 1. soubor (ten co se hned začne přehrávat) se skrytý nenastaví.

Nevíte, prosím vás, proč?

Děkuji.

Tak smazání funguje s deleteOnExit(); bez problému. (I když jsem volání garbage collector smazal).

Skrytí souborů lze udělat na 100%, ale musím použít nio třídy.

import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Paths;

try {
      Files.setAttribute(Paths.get(absolutní cesta k souboru), "dos:hidden", Boolean.TRUE, LinkOption.NOFOLLOW_LINKS);
      } catch (IOException ex) {
}

Výsledek je úplně stejný - skryje soubor. Sice musím importovat 3 třídy, ale když použiji Runtime, tak se první soubor skrytý nenastaví a nepodařilo se mi zjistit proč.

PS. Nebyl jsi to zrovna ty, kdo říkal, že NIO nepotřebuji?

Zpět do poradny Odpovědět na původní otázku Nahoru