2009-04-15 20 views
13

Tôi đang viết một tiện ích giám sát thư mục trong java (1.6) bằng cách sử dụng phiếu thăm dò tại các khoảng thời gian nhất định sử dụng giá trị dài lastModified. Tôi thấy rằng khi khoảng thời gian bỏ phiếu của tôi nhỏ (giây) và tệp sao chép lớn thì sự kiện thay đổi được kích hoạt trước khi hoàn thành việc sao chép tệp.Làm thế nào để biết liệu đang sao chép tập tin 'đang tiến hành'/hoàn thành trong java (1.6)

Tôi muốn biết liệu có một cách tôi có thể tìm thấy trạng thái của file như trên đường vận chuyển, đầy đủ, vv

môi trường: Java 1.6; dự kiến ​​sẽ làm việc trên các cửa sổ và linux.

+1

Tôi nghĩ rằng bạn có những "bản sao" khía cạnh ngược lại. Điều này đã được yêu cầu trong năm 2009, người kia được yêu cầu vào năm 2013! –

Trả lời

4

Bạn có nghĩa là bạn đang đợi thời gian lastModified để giải quyết? Tốt nhất đó sẽ là một chút hit-and-miss.

Làm cách nào để mở tệp có quyền truy cập ghi (phụ thêm thay vì cắt bớt tệp, dĩ nhiên)? Điều đó sẽ không thành công nếu một quá trình khác vẫn đang cố gắng viết cho nó. Đó là một chút xấu xí, đặc biệt là nó có thể là một trường hợp sử dụng ngoại lệ cho kiểm soát dòng chảy (ick) nhưng tôi nghĩ rằng nó sẽ làm việc.

+0

Điều đó có giả định rằng bạn có quyền ghi vào thư mục đang được giám sát không? (Tôi không có một ý tưởng tốt hơn, tâm trí ...) –

+0

Thanks.I đã thử cách tiếp cận và nó hoạt động trên máy phát triển của tôi nhưng cùng suy nghĩ như bình luận trước đó vì tôi không chắc chắn về quyền người dùng triển khai –

+0

@simonn: Có, điều đó phụ thuộc vào bạn có quyền ghi, không vào thư mục nhưng đối với tệp. –

1

Nếu tôi hiểu câu hỏi một cách chính xác, bạn đang tìm cách để phân biệt liệu việc sao chép tệp hoàn tất hay vẫn đang trong quá trình xử lý?

Cách so sánh kích thước tệp nguồn và tệp đích (ví dụ: tệp.length())? Nếu chúng bằng nhau, thì sao chép hoàn tất. Nếu không, nó vẫn đang trong tiến trình.

Tôi không chắc nó hiệu quả vì nó vẫn yêu cầu bỏ phiếu. Nhưng nó "có thể" làm việc.

7

Có hai cách tiếp cận mà tôi đã sử dụng trong quá khứ là nền tảng bất khả tri.

1/Đây là dịch vụ chuyển giao FTP, nơi tôi kiểm soát những gì đã được đặt, vì vậy nó có thể không liên quan trực tiếp.

Về cơ bản, bất cứ điều gì đang đặt một tệp file.txt sẽ, khi kết thúc, cũng đặt một tệp giả nhỏ (có thể là 0 byte) được gọi là file.txt.marker (ví dụ).

Bằng cách đó, công cụ giám sát chỉ tìm kiếm tệp đánh dấu xuất hiện và khi thực hiện, nó biết tệp thực sự đã hoàn tất. Sau đó, nó có thể xử lý tệp thực và xóa điểm đánh dấu.

2/Thời lượng không đổi.

Để chương trình giám sát của bạn đợi cho đến khi tệp không thay đổi trong N giây (trong đó N được đảm bảo hợp lý đủ lớn để tệp sẽ hoàn tất).

Ví dụ: nếu kích thước tệp không thay đổi sau 60 giây, sẽ có cơ hội tốt khi kết thúc.

Có một hành động cân bằng giữa việc không nghĩ rằng tệp được hoàn thành chỉ vì không có hoạt động trên đó và chờ một khi nó được hoàn tất trước khi bạn có thể bắt đầu xử lý nó. Đây là một vấn đề đối với việc sao chép cục bộ hơn FTP.

+3

Tôi đã thử phương pháp thứ hai trên cửa sổ và thấy tệp đó.length() mang lại cho tôi kích thước cuối cùng (sau khi hoàn thành sao chép) ngay cả khi bản sao đang được tiến hành. Bất kỳ suy nghĩ nào về điều này –

+0

Có, hoặc sử dụng cùng một cách tiếp cận nhưng với thời gian cập nhật lần cuối hoặc sử dụng cả kích thước và thời gian. Nhưng tôi ngạc nhiên vì sự khẳng định của bạn - những gì thực sự đang thực hiện việc sao chép? Explorer sẽ không tạo toàn bộ tệp lên phía trước. Bittorrent và các trình tăng tốc tải xuống khác là điều duy nhất tôi thấy được. – paxdiablo

+0

Tôi đang thực hiện sao chép/dán tệp thủ công trong trình khám phá –

5

Giải pháp này làm việc cho tôi:

File ff = new File(fileStr); 

if(ff.exists()) { 

    for(int timeout = 100; timeout>0; timeout--) { 
     RandomAccessFile ran = null; 

     try { 
      ran = new RandomAccessFile(ff, "rw"); 
      break; // no errors, done waiting 
     } catch (Exception ex) { 
      System.out.println("timeout: " + timeout + ": " + ex.getMessage()); 
     } finally { 
      if(ran != null) try { 
       ran.close(); 
      } catch (IOException ex) { 
       //do nothing 
      } 

      ran = null; 
     } 

     try { 
      Thread.sleep(100); // wait a bit then try again 
     } catch (InterruptedException ex) { 
      //do nothing 
     } 
    } 

    System.out.println("File lockable: " + fileStr + 
       (ff.exists()?" exists":" deleted during process")); 
} else { 
    System.out.println("File does not exist: " + fileStr); 
} 

Giải pháp này dựa trên thực tế là bạn không thể mở các tập tin để viết nếu quá trình khác có nó mở. Nó sẽ ở trong vòng lặp cho đến khi đạt được giá trị thời gian chờ hoặc tệp có thể được mở. Các giá trị thời gian chờ sẽ cần phải được điều chỉnh tùy thuộc vào nhu cầu thực tế của ứng dụng. Tôi cũng đã thử phương pháp này với các kênh và tryLock(), nhưng dường như không cần thiết.

+3

Tôi tin rằng điều này hoạt động trong Windows/OS chỉ với khóa manadatory, nhưng không phải là Linux Tại thời điểm này, chúng tôi không chắc chắn nhà văn có được bất kỳ khóa nào (cấp java và hệ điều hành) hay không en.wikipedia.org/wiki/File_locking Tôi chạy trên mã trong Linux có vẻ như quá trình và nhận được quyền truy cập đọc vào một tập tin được viết mà không có bất kỳ ngoại lệ – vincentlcy

+0

là có bất kỳ cách nào cho điều này trong Linux –

1

Chúng tôi đã sử dụng để theo dõi thay đổi Kích thước tệp để xác định xem Tệp có đang trong trạng thái không đầy đủ hay không.

chúng tôi đã sử dụng điểm kết thúc Tập tin kết hợp mùa xuân để thực hiện bỏ phiếu cho một thư mục trong mỗi 200 ms.

Khi tệp được phát hiện (bất kể tệp đó có hoàn chỉnh hay không), chúng tôi có bộ lọc tệp khách hàng, sẽ có phương thức giao diện "chấp nhận (tệp tệp)" để trả lại cờ cho biết chúng tôi có thể xử lý tập tin.

Nếu False được trả lại bởi bộ lọc, ví dụ FILE này sẽ bị bỏ qua và nó sẽ được đón trong bầu cử tiếp theo cho quá trình lọc cùng ..

Bộ lọc nào sau đây:

Đầu tiên, chúng tôi nhận được kích thước tập tin hiện tại của nó. và chúng tôi sẽ chờ 200ms (có thể ít hơn) và kiểm tra lại kích thước. Nếu kích thước khác, chúng tôi sẽ thử lại 5 lần. Chỉ khi kích thước tệp ngừng tăng, Tệp sẽ được đánh dấu là ĐÃ HOÀN THÀNH (nghĩa là trả lại đúng).

Mẫu mã sử dụng là như sau:

public class InCompleteFileFilter<F> extends AbstractFileListFilter<F> { 

    protected Object monitor = new Object(); 
    @Override 
    protected boolean accept(F file) { 
    synchronized (monitor){ 

     File currentFile = (File)file; 

     if(!currentFile.getName().contains("Conv1")){return false;} 

     long currentSize = currentFile.length(); 
     try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } 
     int retryCount = 0; 
     while(retryCount++ < 4 && currentFile.length() > currentSize){ 
      try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } 
     } 

     if(retryCount == 5){ 
      return false; 
     }else{ 
      return true; 
     } 
    } 
    } 
} 
Các vấn đề liên quan