2010-03-25 29 views
14

Tôi có một ứng dụng phải kiểm tra một thư mục và đọc bất kỳ tệp nào được sao chép vào nó hay không. Làm cách nào để kiểm tra xem tệp trong thư mục đó hiện có đang được ghi vào không? Tôi chỉ muốn đọc các tập tin mà đã có tất cả dữ liệu của họ được viết cho họ và bị đóng.Cách kiểm tra xem một tệp hiện có đang được ghi vào

+2

@willsan - Hãy nhớ chấp nhận câu trả lời nếu nó giúp bạn. –

Trả lời

17

Nó không phải là sạch, nhưng nó hoạt động:

try 
{ 
    using (Stream stream = new FileStream("File.txt")) 
    { 
    } 
} 
catch 
{ 
    // Check if file is in use (or whatever else went wrong), and do any user communication that you need to 
} 

tôi không đặc biệt như sử dụng ngoại lệ như điều kiện, nhưng như xa như tôi biết điều này là về dễ nhất và tốt nhất (và duy nhất đáng tin cậy) cách để làm điều này.

+0

Tôi nghĩ try-catch về cơ bản là cách duy nhất không an toàn để kiểm tra tệp. Quá xấu, họ không có thuộc tính IsOpen trong các lớp File hoặc FileInfo .. –

+1

+1: Đây là cách ** CHỈ ** để thực hiện. Hình ảnh có một cuộc gọi trên đối tượng tập tin "IsOpen", không có gì ngăn chặn một quá trình khóa tập tin giữa bạn gọi IsOpen và bạn mở tập tin. Cách duy nhất để xem bạn có thể lấy khóa hay không là cố gắng khóa nó (và sau đó giữ nó khóa). –

+0

Vấn đề anh đang cố gắng giải quyết vốn dễ bị điều kiện chủng tộc. Như tôi đã giải thích trong câu trả lời của tôi dưới đây, thực sự cách tiếp cận được liệt kê ở trên sẽ thất bại nếu "quá trình viết" ghi một đoạn tại một thời điểm (đóng tệp giữa các lần ghi liên tiếp). Tôi nghĩ rằng có quá trình như vậy có nhiều khả năng hơn là có một quá trình không viết gì trong X giây, và sau đó đột nhiên khởi động lại bằng văn bản ngay khi bạn bắt đầu thực hiện công việc của mình. Dù sao, bất kể cách tiếp cận nào, cần phải đồng bộ hóa bổ sung. – Virgil

1

Điều duy nhất tôi có thể nghĩ là khóa tệp sẽ được đưa vào tệp trong khi tệp đang được ghi vào, do đó ngăn không cho bạn ghi vào nó (ném ngoại lệ System.IO của tệp đang bị khóa bởi một quy trình khác), nhưng điều này là không dễ dàng. Ví dụ, tệp có thể được ghi thành từng phần bằng cách mở và đóng tệp cho từng đoạn.

Vì vậy, bạn có thể làm điều này với một khối try/catch:

try 
{ 
    //opening the file 
} 
catch(IOException ex) 
{ 
    // file is open by another process 
} 
0

Số các tùy chọn. Một trong những lò xo để tâm trí ngay lập tức là cố gắng mở tập tin để viết. Nếu bạn nêu một ngoại lệ, nó vẫn đang được ghi vào. Đợi một khoảng thời gian xác định và thử lại.

Ngoài ra kiểm tra timestamps và chỉ cố gắng đọc các tập tin 1 hoặc 2 phút sau khi timestamp cuối cùng đã thay đổi

1

Khi bạn mở nó với System.IO.File.OpenWrite(filename), nó nên ném IOException.

Vì vậy, trong một lần thử, mã đang được thực hiện trong khối catch sẽ cho bạn biết tệp đã được mở.

1

Tệp được ghi vào thường sẽ có khóa ghi trên đó vì vậy nếu bạn cố mở nó để ghi, bạn sẽ thất bại; nhưng OTOH bạn có thể có một quá trình mở, viết và đóng tệp - sau đó lặp lại. Tôi nghĩ rằng cách đơn giản và an toàn nhất sẽ đơn giản là kiểm tra các tệp đã được viết gần đây, nhưng không phải gần đây (ví dụ: không phải trong 2 giây gần đây nhất)

[le] Một điểm cần lưu ý là nếu bạn có một quá trình ghi dữ liệu trong chunck (open-write-close) và bạn nhận được một khóa độc quyền cho tệp (để kiểm tra xem tệp đó không còn được sử dụng) - hơn là quá trình bên ngoài của bạn sẽ thất bại. Tôi nghĩ rằng nó tốt hơn nhiều để kiểm tra các dấu thời gian, và chỉ nhận được khóa độc quyền sau khi bạn hợp lý chắc chắn rằng quá trình khác hoàn thành bằng văn bản.

+0

Quy trình bên ngoài cũng nên xử lý trường hợp này. Để đưa ra một ví dụ như bạn đang nói, viết vào nhật ký, hoặc nhật ký chung, được chia sẻ giữa các quá trình. Nhật ký được mở ra bất cứ khi nào nó cần thiết bởi một số quy trình, quá trình đó có trách nhiệm thu khóa tệp một cách an toàn. Nếu nó không đạt được khóa tập tin là nên xử lý ngoại lệ đúng như ngủ một chút hoặc thử lại sau một thời gian. Nếu bạn chỉ xem tem thời gian thì không có cách nào đáng tin cậy để biết bằng dấu thời gian mà nhật ký sẽ được ghi vào khi bạn cố gắng lấy khóa tệp. – galford13x

+0

Từ khóa ở đây là "nên". Tất cả chúng ta bây giờ mà không phải tất cả các ứng dụng đều .... hoàn hảo. Ý tưởng là bạn biết vài điều về quá trình bên ngoài viết các tệp đó và quá trình đó có thể nằm ngoài tầm kiểm soát của bạn. – Virgil

2

lẽ mở các tập tin độc quyền như thế này -

System.IO.File.Open(PathToFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None); 

Điều đó có thể được đặt trong một vòng lặp với một try/catch cho đến khi thành công.

+1

Bạn có thể muốn thử lại có điều kiện trong khi bắt. Tôi thường có một truy cập và một Thread.Sleep (500) vì vậy tôi không pound I/O và vẫn có thể bảo lãnh nếu một cái gì đó như một vụ tai nạn đĩa xảy ra. –

2

bắt ngoại lệ là tốn kém, bạn nên cố gắng sử dụng này:

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

Có một ví dụ siêu rõ ràng trên trang MSDN. Điều đó sẽ cung cấp cho bạn các sự kiện thú vị về thay đổi, tạo, xóa, đổi tên.

sao chép tệp vào thư mục và đổi tên khi bạn thực hiện bắt sự kiện đổi tên và chắc chắn rằng bạn chưa đọc tệp chưa hoàn tất.

Hoặc bạn có thể nắm bắt các sự kiện thay đổi cho đến khi (điều này là khôn lanh) họ không bị sa thải nữa.

+0

Thật không may, trong trường hợp của tôi tập tin được ghi là từ một chương trình của bên thứ ba. – Ernest

+0

@ErnestSoeralaya Điều này không quan trọng đối với tất cả các chương trình ghi vào tệp bạn đang xem. – albertjan

+0

Sẽ không đổi tên tệp đang được tạo yêu cầu khả năng thay đổi hành vi của chương trình như vậy? – Ernest

0

Nếu bạn có bất kỳ kiểm soát quá trình mà không được viết trong, sau đó xem xét làm tăng nó vì vậy quá trình sau sẽ xảy ra:

  1. Process bắt đầu viết tập tin "filename.xyz"
  2. Process viết hơn nộp "filename.xyz"
  3. ....
  4. ....
  5. Process kết thúc tập tin văn bản "filename.xyz"
  6. Process s ghi tệp khác (không có chiều dài, trống) vào thư mục có tên "filename.xyz.done"

Bạn có thể tìm kiếm tệp ".done" làm trình kích hoạt để bắt đầu xử lý tệp. Một lần nữa, điều này sẽ chỉ hoạt động nếu bạn có bất kỳ cách nào để sửa đổi quá trình thực hiện việc ghi vào các tệp.

Các vấn đề liên quan