2009-02-04 30 views
8

Tôi cần tạo một chương trình java để tạo chuỗi để tìm kiếm tệp trong thư mục nguồn (thư mục nguồn) và chọn tệp ngay lập tức để xử lý (chuyển đổi thành định dạng tệp csv) sau khi tìm thấy tệp trong thư mục nguồn. Vấn đề tôi đang gặp bây giờ là tập tin đến thư mục nguồn là kích thước lớn (công cụ FTP được sử dụng để sao chép tập tin từ máy chủ sang thư mục nguồn), thread sẽ chọn tập tin đó ngay trước khi nó sao chép hoàn toàn vào thư mục nguồn và ném ngoại lệ. Làm cách nào để dừng chuỗi cho đến khi tệp sao chép hoàn toàn vào thư mục nguồn ?. Nó phải chọn tệp để xử lý chỉ sau khi tệp được sao chép hoàn toàn vào thư mục nguồn.Làm cách nào để xử lý các tệp không đầy đủ? Nhận ngoại lệ

+0

Điều tốt để biết, ngoại lệ là gì? –

Trả lời

1

Giả sử bạn không có quyền kiểm soát quá trình FTP ...

Hãy để nó như thế này. Khi bạn nhận được ngoại lệ, hãy thử xử lý lại lần sau. Lặp lại nó cho đến khi tệp được xử lý. Tốt của nó để giữ vài thuộc tính trong trường hợp ngoại lệ để kiểm tra nó sau này, như; tên, được sửa đổi lần cuối, kích thước.

Kiểm tra ngoại lệ chính xác trước khi quyết định xử lý sau, ngoại lệ có thể xảy ra vì một số lý do khác.

2

Nếu bạn có một số điều khiển trên quy trình thực hiện FTP, bạn có khả năng tạo ra một "tệp cờ" trong thư mục nguồn ngay sau khi hoàn thành tệp ftp cho tệp lớn.

Sau đó, chuỗi Java của bạn phải kiểm tra sự hiện diện của tệp cờ này, nếu có, sau đó có tệp sẵn sàng để được xử lý trong thư mục nguồn. Trước khi xử lý tệp lớn, chuỗi nên xóa tệp cờ.

Tệp cờ có thể là bất kỳ thứ gì (kể cả tệp trống).

3

Bạn có thể thử những điều khác nhau:

  • Liên tiếp kiểm tra ngày sửa đổi cuối cùng và kích thước của tập tin cho đến khi nó không thay đổi nữa trong một khoảng thời gian nhất định, sau đó xử lý nó. (Như được chỉ ra bởi qbeuek, điều này không an toàn cũng không xác định.)
  • Chỉ xử lý các tệp có tên khớp với các tiêu chí nhất định (ví dụ: * .dat). Thay đổi quá trình tải lên/tải xuống FTP để tải lên/tải xuống các tệp có tên khác (ví dụ: * .dat.temp) và đổi tên tệp khi chúng hoàn tất.
  • Tải tệp xuống một vị trí khác và di chuyển chúng vào thư mục xử lý của bạn sau khi chúng hoàn tất.
  • Như Giấm đã nói, nếu nó không hoạt động lần đầu tiên, hãy thử lại sau. :)
+0

Tôi không biết tại sao chúng ta có downvotes, đôi khi. Mọi người bắt đầu quay phim ở mọi nơi. 100 danh tiếng là quá thấp để downvote ai đó. Nó phải cao hơn, có thể là 1000 hoặc 2000. –

+0

Vâng, đôi khi tôi bỏ phiếu công cụ chỉ để cân bằng downvotes, cho votee 8 điểm mà họ sẽ không nhận được, vì vậy đó là một cái gì đó. Trong trường hợp này, tôi sẽ bình chọn câu trả lời của bạn, khó khăn. – itsadok

+0

tôi đã bỏ phiếu cho bạn xuống, vì mục đầu tiên trong danh sách đề xuất của bạn không an toàn cũng không xác định. – qbeuek

4

Cách an toàn nhất là tải tệp xuống vị trí khác và sau đó di chuyển tệp đến thư mục đích.

Một biến thể khác được đề cập bởi Bombe là thay đổi tên tệp thành một số tiện ích mở rộng khác sau khi tải xuống và chỉ tìm kiếm tệp có phần mở rộng đó.

+0

+1 Đây không phải là cách an toàn nhất mà là cách duy nhất để thực hiện việc này. Tất cả các tùy chọn khác hoặc là lãng phí tài nguyên hoặc không an toàn :) –

4

Tôi chỉ đọc tệp không ở chế độ ghi. Điều này là an toàn nhất vì điều này có nghĩa là không có quy trình nào khác được viết trong tệp này. Bạn có thể kiểm tra xem tệp có ở chế độ ghi không bằng cách sử dụng phương thức canWrite của lớp File.

Giải pháp này có tác dụng tốt đối với tôi vì tôi cũng có cùng một trường hợp bạn gặp phải.

0

Nếu hệ điều hành của bạn là Linux và hạt nhân của bạn> 2.6.13, bạn có thể sử dụng API thông báo sự kiện hệ thống tệp có tên inotify. Có triển khai Java tại đây: https://bitbucket.org/nbargnesi/inotify-java.

Đây là mã mẫu (được lấy cảm hứng từ trang web).

 try { 
     Inotify i = new Inotify(); 
     InotifyEventListener e = new InotifyEventListener() { 

      @Override 
      public void filesystemEventOccurred(InotifyEvent e) { 
       System.out.println("inotify event occurred!"); 
      } 

      @Override 
      public void queueFull(EventQueueFull e) { 
       System.out.println("inotify event queue: " + e.getSource() + 
         " is full!"); 
      } 

     }; 
     i.addInotifyEventListener(e); 
     i.addWatch(System.getProperty("user.home"), Constants.IN_CLOSE_WRITE); 
    } catch (UnsatisfiedLinkError e) { 
     System.err.println("unsatisfied link error"); 
    } catch (UserLimitException e) { 
     System.err.println("user limit exception"); 
    } catch (SystemLimitException e) { 
     System.err.println("system limit exception"); 
    } catch (InsufficientKernelMemoryException e) { 
     System.err.println("insufficient kernel memory exception"); 
    } 
0

Đây là trong Grails và tôi đang sử dụng FileUtils Thư viện từ danh tiếng của cộng đồng Apache. Hàm sizeof trả về kích thước tính theo byte.

def fileModified = sourceFile.lastModified() 
    def fileSize = FileUtils.sizeOf(sourceFile) 

    Thread.sleep(3000) //sleep to calculate size difference if the file is currently getting copied 

    if((fileSize != FileUtils.sizeOf(sourceFile)) && (fileModified != sourceFile.lastModified())) //the file is still getting copied to return 
    { 
     if(log.infoEnabled) 
      log.info("File is getting copied!") 
     return 
    } 

    Thread.sleep(1000) //breather for picking up file just copied. 

Xin lưu ý rằng điều này cũng phụ thuộc vào những gì hữu ích, hệ điều hành bạn đang sử dụng để chuyển các tập tin. Đặt cược an toàn nhất là sao chép tệp đã được sao chép hoặc đã được sao chép sang tệp hoặc thư mục khác. Quá trình sao chép là một quá trình mạnh mẽ và nó đảm bảo với bạn rằng tệp có mặt sau quá trình sao chép. Một trong những tôi đang sử dụng là từ commons API.

FileUtils.copyFileToDirectory (File f, Directory D)

Nếu bạn đang sao chép một tập tin khổng lồ mà là trong quá trình của việc sao chép hãy cẩn thận rằng điều này sẽ mất nhiều thời gian và bạn có thể muốn bắt đầu này trong chủ đề song song hoặc tốt nhất có một ứng dụng riêng biệt dành riêng cho quá trình chuyển giao.