Пытаюсь удалить файл, написав что-то в нем, с расширением 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()
все возвращаются правда. Сразу после вызова этих методов я пытаюсь file.delete()
вернуть false.
Что-то я сделал не так?
java
file
fileoutputstream
Дженни Смит
источник
источник
Ответы:
Еще один баг в Java. Я их редко нахожу, только второй за 10 лет карьеры. Это мое решение, как уже упоминали другие. Я не использовал ее
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(); } }
источник
new File(path)
), я столкнулся с той же проблемой и добавлениемSystem.gc()
до того, какdelete()
он заработал!System.gc
трюк срабатывает каждый раз.System.gc(); result = file.delete(); if (!result){ Thread.sleep(100); System.gc(); result = file.delete(); }
Это был довольно странный трюк, который сработал. Дело в том, что когда я предварительно прочитал содержимое файла, я использовал
BufferedReader
. После прочтения закрыл буфер.Тем временем я переключился и теперь читаю контент с помощью
FileInputStream
. Также после прочтения закрываю поток. И теперь все работает.Проблема в том, что у меня нет объяснения этому.
Не знаю
BufferedReader
иFileOutputStream
быть несовместимым.источник
finalize()
чтобы организовать уборку? Или, может быть, установитьto = null
? См. Раздел « Принудительная финализация и сборка мусора» .Я попробовал эту простую вещь, и, похоже, она работает.
file.setWritable(true); file.delete();
Меня устраивает.
Если это не сработает, попробуйте запустить приложение Java с помощью sudo, если в Linux, и от имени администратора, если в Windows. Просто чтобы убедиться, что Java имеет права изменять свойства файла.
источник
Прежде чем пытаться удалить / переименовать какой-либо файл, вы должны убедиться, что все читатели или писатели (например:
BufferedReader
/InputStreamReader
/BufferedWriter
) должным образом закрыты.Когда вы пытаетесь прочитать / записать данные из / в файл, файл удерживается процессом и не освобождается до завершения выполнения программы. Если вы хотите выполнить операции удаления / переименования до завершения программы, вы должны использовать
close()
метод, поставляемый сjava.io.*
классами.источник
Как прокомментировал Джон Скит, вам следует закрыть файл в блоке 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); }
Итак, я знаю, что содержимое файла там. Поскольку для меня обычно важно, чтобы содержимое файла было записано, а не то, можно ли закрыть файл или нет, на самом деле не имеет значения, был ли файл закрыт или нет. В вашем случае, если это важно, я бы рекомендовал закрыть файл самостоятельно и обработать любые исключения в соответствии с ним.
источник
Нет причин, по которым вы не можете удалить этот файл. Я бы посмотрел, кто держит этот файл. В unix / linux вы можете использовать утилиту lsof, чтобы проверить, какой процесс заблокировал файл. В Windows вы можете использовать проводник процессов.
для lsof это так же просто, как сказать:
для проводника процессов вы можете использовать меню поиска и ввести имя файла, чтобы показать вам дескриптор, который укажет вам на процесс, блокирующий файл.
вот код, который делает то, что я думаю, вам нужно делать:
FileOutputStream to; try { String file = "/tmp/will_delete.txt"; to = new FileOutputStream(file ); to.write(new String("blah blah").getBytes()); to.flush(); to.close(); File f = new File(file); System.out.print(f.delete()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
Он отлично работает в OS X. Я не тестировал его в Windows, но подозреваю, что он должен работать и в Windows. Я также признаю, что видел некоторое неожиданное поведение при обработке файлов Windows.
источник
Если вы работаете в среде Eclipse IDE, это может означать, что вы не закрывали файл при предыдущем запуске приложения. Когда у меня было такое же сообщение об ошибке при попытке удалить файл, это было причиной. Похоже, Eclipse IDE не закрывает все файлы после завершения работы приложения.
источник
Надеюсь, это поможет. Я столкнулся с аналогичной проблемой, когда я не мог удалить свой файл после того, как мой java-код скопировал содержимое в другую папку. После обширного поиска в Google я явно объявил все переменные, связанные с файловой операцией, и вызвал метод close () для каждого объекта файловой операции и установил для них значение NULL. Затем есть функция под названием System.gc (), которая очищает отображение файлового ввода-вывода (я не уверен, я просто говорю, что указано на веб-сайтах).
Вот мой пример кода:
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(); } }
источник
ответ: когда вы загружаете файл, вам нужно применить метод "close" в любой строке кода, работает со мной
источник
Однажды в Ruby возникла проблема, когда файлам в Windows требовался "fsync", чтобы на самом деле иметь возможность развернуть и перечитать файл после его записи и закрытия. Возможно, это аналогичное проявление (и если да, то я действительно думаю, что это ошибка Windows).
источник
Ни одно из перечисленных здесь решений не помогло в моей ситуации. Мое решение состояло в том, чтобы использовать цикл 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 и т. Д.
источник
Проблема может заключаться в том, что файл все еще рассматривается как открытый и заблокированный программой; или, возможно, это компонент вашей программы, в котором он был открыт, поэтому вы должны убедиться, что используете
dispose()
метод для решения этой проблемы. т.е.JFrame frame; .... frame.dispose();
источник
Вы должны закрыть все потоки или использовать блок 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; }
источник
если file.delete () отправляет false, то в большинстве случаев ваш дескриптор Bufferedreader не будет закрыт. Просто закройтесь и у меня вроде нормально работает.
источник
У меня была такая же проблема в Windows. Раньше я читал файл в scala построчно с
Сейчас читаю целиком с
import org.apache.commons.io.FileUtils._ // encoding is null for platform default val content=readFileToString(new File(path),null.asInstanceOf[String])
который закрывает файл после чтения и теперь
new File(path).delete
работает.
источник
Перезагрузите IDE и снова запустите свой код, это всего лишь уловка для меня после часа долгой борьбы.
Вот мой код:
File file = new File("file-path"); if(file.exists()){ if(file.delete()){ System.out.println("Delete"); } else{ System.out.println("not delete"); } }
Выход:
удалять
источник
Другой угловой случай, когда это могло произойти: если вы читаете / записываете файл JAR через a
URL
и позже пытаетесь удалить тот же файл в том же сеансе JVM.File f = new File("/tmp/foo.jar"); URL j = f.toURI().toURL(); URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF"); URLConnection c = u.openConnection(); // open a Jar entry in auto-closing manner try (InputStream i = c.getInputStream()) { // just read some stuff; for demonstration purposes only byte[] first16 = new byte[16]; i.read(first16); System.out.println(new String(first16)); } // ... // i is now closed, so we should be good to delete the jar; but... System.out.println(f.delete()); // says false!
Причина в том, что внутренняя логика обработки файлов JAR в Java имеет тенденцию к кэшированию
JarFile
записей:// inner class of `JarURLConnection` that wraps the actual stream returned by `getInputStream()` class JarURLInputStream extends FilterInputStream { JarURLInputStream(InputStream var2) { super(var2); } public void close() throws IOException { try { super.close(); } finally { // if `getUseCaches()` is set, `jarFile` won't get closed! if (!JarURLConnection.this.getUseCaches()) { JarURLConnection.this.jarFile.close(); } } } }
И каждая
JarFile
(скорее, базоваяZipFile
структура) будет содержать дескриптор файла с момента создания до моментаclose()
вызова:public ZipFile(File file, int mode, Charset charset) throws IOException { // ... jzfile = open(name, mode, file.lastModified(), usemmap); // ... } // ... private static native long open(String name, int mode, long lastModified, boolean usemmap) throws IOException;
Есть хорошее объяснение этой проблемы NetBeans .
По-видимому, есть два способа "исправить" это:
Вы можете отключить кеширование файлов JAR - для текущего
URLConnection
или для всех будущихURLConnection
(глобально) в текущем сеансе JVM:URL u = new URL("jar:" + j + "!/META-INF/MANIFEST.MF"); URLConnection c = u.openConnection(); // for only c c.setUseCaches(false); // globally; for some reason this method is not static, // so we still need to access it through a URLConnection instance :( c.setDefaultUseCaches(false);
[HACK WARNING!] Вы можете вручную очистить
JarFile
кеш, когда закончите с ним. Кеш-менеджерsun.net.www.protocol.jar.JarFileFactory
является частным для пакета, но некоторая магия отражения может сделать эту работу за вас:class JarBridge { static void closeJar(URL url) throws Exception { // JarFileFactory jarFactory = JarFileFactory.getInstance(); Class<?> jarFactoryClazz = Class.forName("sun.net.www.protocol.jar.JarFileFactory"); Method getInstance = jarFactoryClazz.getMethod("getInstance"); getInstance.setAccessible(true); Object jarFactory = getInstance.invoke(jarFactoryClazz); // JarFile jarFile = jarFactory.get(url); Method get = jarFactoryClazz.getMethod("get", URL.class); get.setAccessible(true); Object jarFile = get.invoke(jarFactory, url); // jarFactory.close(jarFile); Method close = jarFactoryClazz.getMethod("close", JarFile.class); close.setAccessible(true); //noinspection JavaReflectionInvocation close.invoke(jarFactory, jarFile); // jarFile.close(); ((JarFile) jarFile).close(); } } // and in your code: // i is now closed, so we should be good to delete the jar JarBridge.closeJar(j); System.out.println(f.delete()); // says true, phew.
Обратите внимание: все это основано на кодовой базе Java 8 (
1.8.0_144
); они могут не работать с другими / более поздними версиями.источник