2009-07-20 31 views
12

Tôi đang theo dõi một thư mục cho các tệp mới và cần xử lý chúng. Vấn đề là thỉnh thoảng mở tệp không thành công, vì hệ thống chưa hoàn tất việc sao chép tệp.Cách kiểm tra xem tệp có được sao chép hoàn toàn trong .NET

Cách chính xác để kiểm tra xem tệp có được sao chép xong không?

Làm rõ: Tôi không có quyền ghi vào thư mục/tệp và không thể kiểm soát quá trình sao chép (đó là người dùng).

+0

Câu hỏi hay! Khi tôi đã có vấn đề đó, tôi chỉ cần thêm System.Threading.Thread.Sleep (1000), nhưng tôi sẽ * yêu * để có được một giải pháp tốt hơn (Nó chỉ là như vậy lame ...) – Treb

+0

Bạn có quyền truy cập đọc vào tập tin gốc, đang được sao chép? –

Trả lời

11

Tôi nghĩ rằng cách chắc chắn duy nhất để làm điều này là cố gắng mở tệp độc quyền và bắt ngoại lệ cụ thể.Tôi thường ghét sử dụng ngoại lệ đối với logic ứng dụng bình thường, nhưng tôi sợ cho kịch bản này không có cách nào khác (ít nhất tôi đã không tìm thấy một chưa):

public bool FileIsDone(string path) 
{ 
    try 
    { 
    using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None)) 
    { 
    } 
    } 
    catch(UnauthorizedAccessException) 
    { 
    return false; 
    } 

    return true; 
} 
0

một cách tiếp cận mà tôi luôn thực hiện là tạo tệp ở cuối bản sao/chuyển của tôi có tên là "token.txt" không có nội dung. Ý tưởng là tập tin này sẽ được tạo ra ngay khi kết thúc thao tác chuyển, vì vậy bạn có thể theo dõi việc tạo tập tin này và khi tập tin này được tạo, bạn bắt đầu làm việc với các tập tin của bạn. Đừng quên xóa tập tin mã thông báo này khi bạn bắt đầu xử lý các tệp của mình.

+1

Nhưng nếu tài khoản người dùng không có quyền xóa tệp trong máy chủ thì phương pháp này sẽ không sử dụng được. – rahul

+2

Đừng nghĩ rằng extropy đang chờ đợi một quá trình sao chép bản thân mình như kiểm soát. Vì vậy, sau đó sẽ không có tập tin mã thông báo, phải không? – peSHIr

+1

tôi nghĩ rằng bạn không thể nói nếu anh ta có hoặc không truy cập/kiểm soát mà không có một quá trình mà không có thêm chi tiết. Nó giống như một cơn động não, nơi mọi người cho đầu vào. –

0

Bạn cũng nên bao gồm các trường hợp như: tập tin được sử dụng bởi chương trình khác, tập tin đã bị xóa (bản sao đã không thành công) vv ..

Sử dụng một ngoại lệ mở rộng xử lý để trang trải tất cả các trường hợp quan trọng có thể xảy ra.

2

Không chắc chắn về "đúng cách", nhưng bạn có thể sử dụng công cụ giám sát (FileSystemWatcher Tôi đoán) để điền vào hàng đợi nội bộ mà bạn sử dụng để xử lý bị trì hoãn. Hoặc tốt hơn: chỉ cần sử dụng hàng đợi để đặt các tệp trong đó có lỗi mở, vì vậy bạn có thể thử lại sau.

1

Nếu bạn đang sử dụng FileSystemWatcher Tôi không nghĩ rằng có một giải pháp mạnh mẽ cho vấn đề này. Một cách tiếp cận sẽ là thử/bắt/thử lại sau.

0

Điều đó phụ thuộc, một vòng lặp thử lại có lẽ là điều tốt nhất bạn có thể làm, nếu bạn không có quyền kiểm soát quá trình sao chép.

Nếu bạn có kiểm soát:

  • Nếu thư mục là địa phương, bạn có thể yêu cầu rằng những người viết thứ vào nó khóa các tập tin để truy cập độc quyền, và chỉ nhả khóa khi chúng được thực hiện (trong đó Tôi nghĩ là mặc định cho File.Copy). Về phía Net. Bạn có thể có một vòng lặp thử lại đơn giản, với thời gian nguội xuống.
    • Hoặc bạn có thể ghi tệp vào thư mục tạm thời và chỉ sau khi được ghi bằng văn bản vào thư mục đích. Điều này làm giảm cửa sổ nơi các nội dung xấu có thể xảy ra (nhưng không loại bỏ nó)
  • Nếu thư mục là một phần SMB, có một cơ hội LockFile thậm chí không hoạt động (một số cài đặt Linux). Trong trường hợp đó, cách tiếp cận chung là có một loại tệp khóa, được xóa khi người tạo tệp được thực hiện. Vấn đề với cách tiếp cận tập tin khóa là nếu bạn quên xóa nó, bạn có thể gặp rắc rối.
  • Khi xảy ra các biến chứng này, tôi khuyên bạn nên nhận dữ liệu qua dịch vụ WCF hoặc dịch vụ web có thể thuận lợi vì bạn có quyền kiểm soát tốt hơn nhiều.
0

Trong thực tế, để tránh điều kiện chủng tộc, các chỉ có giải pháp an toàn là thử lại.

Nếu bạn làm điều gì đó như:

while (file is locked) 
    no-op() 
process file() 

Bạn có nguy cơ quá trình khác nhảy vào giữa bảo vệ thời gian và báo cáo kết quả tập tin quá trình. Cho dù bạn đã "chờ tính khả dụng của tệp" như thế nào, trừ khi bạn có thể đảm bảo rằng sau khi mở khóa bạn là quá trình đầu tiên truy cập nó, bạn có thể không phải là là người dùng đầu tiên đó.

Điều này có nhiều khả năng dường như có vẻ thoáng qua, đặc biệt nếu nhiều người đang xem tệp và đặc biệt nếu họ đang sử dụng thứ gì đó giống như trình xem hệ thống tệp. Khóa học, thậm chí nó vẫn không có khả năng đặc biệt ...

0

Các tệp có lớn không?

Có lẽ bạn có thể thử tính toán tổng kiểm tra md5 trên tệp?

Nếu bạn đặt hàm băm md5 vào tên tệp, bạn có thể truy xuất nó và thử tính toán lại tổng kiểm tra trên tệp. Khi md5 là một kết hợp bạn có thể giả định rằng tệp đã hoàn tất.

byte[] md5Hash = null; 
MD5 md5 = new MD5CryptoServiceProvider(); 
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) 
    md5Hash = md5.ComputeHash(fs); 

StringBuilder hex = new StringBuilder(); 
foreach (byte b in md5Hash) 
    hex.Append(b.ToString("x2")); 
0

Đây là vòng lặp vb.net tôi sử dụng. Nó chờ 2 giây giữa mỗi lần kiểm tra.

Dim donotcopy As Boolean = True 
While donotcopy = True 
    Dim myFile As New FileInfo("Filetocopy") 
    Dim sizeInBytes As Long = myFile.Length 
    Thread.Sleep(2000) 
    Dim myFile2 As New FileInfo("Filetocopy") 
    Dim sizeInBytes2 As Long = myFile2.Length 
    If sizeInBytes2 = sizeInBytes Then donotcopy = False 
End While 
Các vấn đề liên quan