即使 file.exists()、file.canRead()、file.canWrite()、file.canExecute() 都返回 true,file.delete() 返回 false
-
13-09-2019 - |
题
我正在尝试删除一个文件,在其中写入一些内容后, 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()
返回假。
我在删除之前检查了该文件是否存在,并且: file.exists()
, file.canRead()
, file.canWrite()
, file.canExecute()
全部返回 true。调用这些方法后我尝试 file.delete()
并返回 false。
我是不是做错了什么?
解决方案 2
这是很奇怪的是,工作的伎俩。问题是,当我以前读取文件的内容,我用BufferedReader
。看完后,我封闭缓冲液。
同时我切换,现在我使用FileInputStream
读取内容。此外读完后,我关闭流。现在,它的工作。
问题是我没有这样做的解释。
不知BufferedReader
和FileOutputStream
是不相容的。
其他提示
在Java中的另一种错误。我很少看到他们,只有我在我的10年职业生涯第二。这是我的解决方案,正如其他人提及。我有幽冥使用System.gc()
。但是在这里,在我而言,这是绝对至关重要的。奇怪的? YES!
finally
{
try
{
in.close();
in = null;
out.flush();
out.close();
out = null;
System.gc();
}
catch (IOException e)
{
logger.error(e.getMessage());
e.printStackTrace();
}
}
我想这个简单的事情,它似乎是工作。
file.setWritable(true);
file.delete();
这对我的作品。
如果这不起作用尝试,如果在Linux上,并以管理员身份运行使用sudo你的Java应用程序在Windows上的时候。只是为了确保Java有权利更改文件属性。
试图删除/重命名的任何文件之前,你必须确保所有的读者和作家(为前:BufferedReader
/ InputStreamReader
/ BufferedWriter
)。正确关闭
当您尝试读取/从/到一个文件,该文件是由进程持有,而不是释放,直到程序运行结束写入数据。如果要执行删除/重命名操作的全部程序结束之前,则必须使用随附close()
类java.io.*
方法。
由于乔恩斯基特评论,应关闭文件中的最后{...}块,以确保它总是关闭。并且,而不是吞咽与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(...),所以我用的冲洗方法,以确保文件的内容是否有之前我尝试关闭它(IOUtils.closeQuietly不抛出异常)。是这样的:
...
try {
...
to.flush();
} catch(IOException ex) {
throw new CannotProcessFileException("whatever", ex);
} finally {
IOUtils.closeQuietly(to);
}
所以我知道该文件的内容都在里面。因为它通常与我有关,该文件的内容写入,而不是如果该文件可能被关闭或没有,真的没有,如果该文件被关闭或没有关系。根据你的情况,因为它很重要,我会建议你自己关闭文件,并根据处理任何异常。
有没有理由,你不应该能够删除这个文件。我想看看,看看谁对这个文件保持。在Unix / Linux操作系统,你可以使用lsof工具来检查哪个进程在文件上的锁。在窗口中,可以使用过程资源管理器。
有lsof的,这是简单的话说:
lsof /path/and/name/of/the/file
有关进程管理器,你可以使用查找菜单,然后输入文件名给你看,这将指向你的过程中锁定该文件句柄。
下面是一些代码,做什么,我认为你需要做的:
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 w.r.t.一些意想不到的行为文件处理。
如果您在Eclipse IDE中工作,这可能意味着你没有关闭该文件在以前启动该应用程序。当我有相同的错误消息在试图删除文件,这是原因。看来,Eclipse IDE中不关闭所有文件的应用程序终止后。
希望这将有助于。我碰到类似的问题在那里后,我的Java代码进行的内容的副本到其他文件夹我无法删除我的文件。广泛的谷歌搜索后,我明确宣布的每一个文件操作有关的变量,并呼吁每个文件操作对象的close()方法,并将其设置为NULL。然后,有一个叫System.gc()的函数,这将清理文件I / O映射(我不知道,我只是告诉什么是对网站给出)。
下面是我的示例代码:
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();
}
}
答案是,当你加载的文件,你需要应用“亲密”的方法,在任何一行代码,工作对我
在红宝石在需要在Windows中的文件的“FSYNC”居然能扭亏为盈,并有一个问题,一旦重新读取该文件。也许这是一个类似的表现(如果有的话,我觉得窗户错误,真的)。
下面列出了我的处境工作的解决方案都不是。我的解决方案是使用一个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--;
}
使用上述循环工作而无需做任何手动垃圾收集或设置流为空,等等。
在问题可能是该文件仍然被视为打开和通过程序来锁定;或者它是从你的,它一直在打开的程序组件,所以你必须确保你使用dispose()
方法来解决这个问题。
即JFrame frame;
....
frame.dispose();
您必须关闭所有的流或使用try-与资源块
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()被发送伪造的,然后在你的大部分的BufferedReader手柄不会被关闭的情况。只是关闭它似乎为我正常工作。
我在Windows同样的问题。我用于读取与
在由线阶行的文件Source.fromFile(path).getLines()
现在我读它作为一个整体与
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
作品。
有关的Eclipse / NetBeans的
重新启动IDE并运行代码这同样是一小时后的长期斗争,我只招工作。
下面是我的代码:
File file = new File("file-path");
if(file.exists()){
if(file.delete()){
System.out.println("Delete");
}
else{
System.out.println("not delete");
}
}
<强>输出:强>
删除
另一个可能发生这种情况的极端情况:如果您通过a读取/写入JAR文件 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!
原因是Java内部JAR文件处理逻辑,倾向于缓存 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 会话中的 s(全局):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);
[黑客警告!] 您可以手动清除
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
);它们可能无法与其他/更高版本一起使用。