Windows에서 java.io.File.renameTo() 메서드가 실패하는 경우에 대하여

By | 6월 2, 2011

Windows 환경에서 java.io.File.renameTo()를 사용하여 파일을 rename 하려고 할때,
아무 이유 없이 랜덤하게 실패
하는 경우가 종종 있었다.
이 renameTo() 메서드는 Exception 도 발생시키지 않고 단지 결과값을 false로 반환할 뿐이어서
난감한 상황이었다.

그래서 구글링을 해 본 결과 다음과 같은 경우에 이런 현상이 발생할 수 있다는 의견을 얻을 수 있었다.

1. A file handle is inherited by a subprocess of your process
2. An anti-virus program is scanning the file for viruses, and so has it open
3. An indexer (such as Google Desktop or the Windows indexing service) has the file open

결국 윈도우에서 무언가가 해당 파일을 물고 있기 때문에 rename을 할 수 없다는 이야기인데,
그나마 다행스러운 것은 윈도우에서만 발생하는 현상 같다는 것이다.

- 참고 -

다음은 이 현상을 가능한한 피해 가기 위해 외국의 어느 개발자가 고안한 대처방안이다.
(File 클래스를 상속받은 클래스를 만들어서 renameTo() 메서드를 오버라이드)
본인의 말에 의하면 완벽하지는 않지만 실패를 꽤 커버해 준다고 한다. 그냥 참고로만 하자.
(완벽하지 않으면 무슨 의미가 -_-;...)

import java.io.File;

public class XFile extends File {

 private XFile(String filePath){
  super(filePath);
 }
 
 /**
  * ==============================================================
  * This method is a cover for File.renameTo(). The motivation for this
  * cover method is that with this new version of Java (1.5.0), rename (and
  * other file methods) sometimes don't work on the first try. This seems to
  * be because file objects that have been closed are hung onto, pending
  * garbage collection.
  *
  * @return true if and only if the renaming succeeded; false otherwise
  * @param pNewFile
  *            is a File customer containing the new name for the file.
  * ==============================================================
  */
 public boolean renameTo(File pNewFile) {
  /*
   * =============================================== HACK - I should just
   * be able to call renameTo() here and return its result. In fact, I
   * used to do just that and this method always worked fine. Now with
   * this new version of Java (1.5.0), rename (and other file methods)
   * sometimes don't work on the first try. This is because file objects
   * that have been closed are hung onto, pending garbage collection. By
   * suggesting garbage collection, the next time, the renameTo() usually
   * (but not always) works.
   * -----------------------------------------------
   */
  //재시도 루프의 적당한 횟수를 20이라고 생각한 듯 하다.
  for (int i = 0; i < 20; i++) {

   if (super.renameTo(pNewFile)) {
    return true;
   }

   //가비지 콜렉션 - 아마도 윈도우가 점유한 메모리를 해제하기 위함인 듯.
   System.gc(); 
   
   try{
    Thread.sleep(50); //처리할 시간적 여유를 주기 위함인듯.
   }catch(InterruptedException ie){
    ie.printStackTrace();
   }
  }
  return false;
 }
 
}

- 출처 -
http://stackoverflow.com/questions/1325388/how-to-find-out-why-renameto-failed
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213298

Subscribe
Notify of
guest
6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
sj
sj
12 years ago

구글링으로 벌써 2주안에 2번째 방문이네요, 감사합니다!

호러블캣
호러블캣
12 years ago

저도 감사합니다!!

말린클로버
말린클로버
12 years ago

정말 유용한정보 감사합니다.

호러블캣
호러블캣
12 years ago

도움이 되었다니 다행입니다~

샤오니
샤오니
2 years ago

감사합니다. 하루종일 안되서 고생했는데 덕분에 해결했어요 ㅠㅠ