file.delete ()는 file.exists (), file.canRead (), file.canWrite (), file.canExecute () 모두가 true를 반환하더라도 false를 반환합니다.
파일을 .NET으로 작성한 후 파일을 삭제하려고합니다 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를 반환합니다.
내가 잘못한 것이 있습니까?
자바의 또 다른 버그. 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();
}
}
효과가있는 속임수는 꽤 이상했습니다. 문제는 이전에 파일의 내용을 읽었을 때 BufferedReader
. 읽은 후 버퍼를 닫았습니다.
그동안 나는 전환했고 지금은 FileInputStream
. 또한 읽기를 마친 후 스트림을 닫습니다. 그리고 이제 작동합니다.
문제는 이것에 대한 설명이 없다는 것입니다.
나도 몰라 BufferedReader
과 FileOutputStream
호환되지 않을 수 있습니다.
나는이 간단한 것을 시도했고 작동하는 것 같다.
file.setWritable(true);
file.delete();
그것은 나를 위해 작동합니다.
이것이 작동하지 않으면 Linux에서는 sudo로, Windows에서는 관리자로 Java 애플리케이션을 실행하십시오. Java에 파일 속성을 변경할 수있는 권한이 있는지 확인하기 위해서입니다.
파일을 삭제 / 이름 변경하기 전에 모든 판독기 또는 작성기 (예 : BufferedReader
/ InputStreamReader
/ BufferedWriter
)가 제대로 닫혔 는지 확인해야합니다 .
파일에서 데이터를 읽고 쓰려고 할 때 파일은 프로세스에 의해 유지되고 프로그램 실행이 완료 될 때까지 해제되지 않습니다. 프로그램이 종료되기 전에 삭제 / 이름 변경 작업을 수행하려면 클래스 close()
와 함께 제공 되는 메서드를 사용해야합니다 java.io.*
.
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);
}
그래서 나는 파일의 내용이 거기에 있다는 것을 알고 있습니다. 일반적으로 파일의 내용이 기록되고 파일을 닫을 수 있는지 여부가 아니라 파일이 닫혔는지 여부는 중요하지 않습니다. 귀하의 경우 중요하므로 파일을 직접 닫고 예외를 처리하는 것이 좋습니다.
이 파일을 삭제할 수없는 이유는 없습니다. 이 파일을 누가 보유하고 있는지 살펴 보겠습니다. 유닉스 / 리눅스에서는 lsof 유틸리티를 사용하여 파일에 잠금이있는 프로세스를 확인할 수 있습니다. Windows에서는 프로세스 탐색기를 사용할 수 있습니다.
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 wrt 파일 처리에서 예상치 못한 동작이 있음을 인정할 것입니다.
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();
}
}
대답은 파일을로드 할 때 코드 줄에 "close"메서드를 적용해야한다는 것입니다.
한때 루비에서는 윈도우의 파일이 파일을 쓰고 닫은 후 실제로 돌아 서서 다시 읽을 수있는 "fsync"가 필요한 문제가있었습니다. 아마도 이것은 비슷한 현상 일 것입니다 (그렇다면 윈도우 버그라고 생각합니다).
여기에 나열된 솔루션 중 어느 것도 내 상황에서 작동하지 않았습니다. 내 해결책은 안전을 위해 5 초 (구성 가능) 제한으로 파일을 삭제하려고 시도하는 while 루프를 사용하는 것이 었습니다.
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에서 파일을 한 줄씩 읽었습니다.
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");
}
}
산출:
지우다
Another corner case that this could happen: if you read/write a JAR file through a URL
and later try to delete the same file within the same JVM session.
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!
Reason is that the internal JAR file handling logic of Java, tends to cache JarFile
entries:
// 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();
}
}
}
}
And each JarFile
(rather, the underlying ZipFile
structure) would hold a handle to the file, right from the time of construction up until close()
is invoked:
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;
There's a good explanation on this NetBeans issue.
Apparently there are two ways to "fix" this:
You can disable the JAR file caching - for the current
URLConnection
, or for all futureURLConnection
s (globally) in the current JVM session: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!] You can manually purge the
JarFile
from the cache when you are done with it. The cache managersun.net.www.protocol.jar.JarFileFactory
is package-private, but some reflection magic can get the job done for you: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.
Please note: All this is based on Java 8 codebase (1.8.0_144
); they may not work with other / later versions.
'Programing' 카테고리의 다른 글
HTML에 유니 코드 기호 표시 (0) | 2020.09.15 |
---|---|
Swift에서 함수 매개 변수로 프로토콜을 준수하는 클래스 (0) | 2020.09.14 |
Chrome 확장 : popup.html을 강제 종료 (0) | 2020.09.14 |
Go에서 부분적으로 JSON을 맵으로 비 정렬 화 (0) | 2020.09.14 |
PHP의 implode에 해당하는 Python? (0) | 2020.09.14 |