2010-10-02 33 views
7

Tôi đang tạo ứng dụng trong C#, trong đó tôi phải mở tệp CSV để đọc dữ liệu từ đó. Tôi nhận được một ngoại lệ khi tôi cố gắng mở tệp CSV từ C# khi tệp đó đã được mở trong Excel. Ngoại lệ nói rằng quá trình không thể truy cập tệp vì nó đã được mở. Làm thế nào tôi có thể giải quyết vấn đề này và mở tập tin ngay cả khi nó được mở trong ứng dụng khác?Ngoại lệ khi mở một tệp đã mở

Xin cảm ơn, Rakesh.

+0

xin vui lòng gửi một số mã để cho chúng ta thấy những gì bạn đã làm cho đến nay – Woot4Moo

+1

Đây là mã: using (FileStream fs = new FileStream (csvOpenFileDialog.FileName, FileMode.Open, FileAccess.Read)) –

+0

Bạn đang thiếu một đối số. Đọc câu trả lời của tôi. – Nayan

Trả lời

7

Tôi đã gặp sự cố này một thời gian.

Bạn thiếu thông số FileShare. Nếu không chỉ rõ rằng, nếu bạn mở một tập tin, nó sẽ bị khóa độc quyền bởi ứng dụng của bạn. Nhưng vì nó đã được Excel mở (hoặc bất kỳ ứng dụng nào khác), bạn sẽ nhận được một ngoại lệ.

Bạn có thể thử sử dụng này - Tôi nghĩ rằng đây sẽ là lựa chọn tốt nhất của bạn -

using (FileStream fs = File.Open(<file-path>, FileMode.Open, FileAccess.Read, FileShare.Read))

Mã này nói: Xin chào Excel! Nếu bạn có thể cho phép (đọc, không ném ngoại lệ), tôi muốn đọc các tập tin, mặc dù tôi sẽ không cố gắng sở hữu nó và tôi biết rằng bạn có thể sửa đổi nó bất cứ lúc nào.

Nếu điều này xảy ra lỗi, thì Excel đã từ chối bạn ngay cả quyền truy cập đọc. Quá tệ rồi! Tất cả tốt nhất.

+2

Tôi tìm thấy FileShare.Read không hoạt động, trong khi FileShare.ReadWrite đã làm –

+1

Không chắc chắn những gì bạn đã làm, nhưng .... tốt của nó - bất cứ điều gì làm việc cho bạn! – Nayan

+0

Sử dụng FileShare.ReadWrite thay vì FileShare.Read, như đã đề cập bởi Hans. –

0

Do vấn đề tương tranh, bạn không thể có tùy chọn ghi vào hai phiên bản của cùng một tệp. Nó sẽ có thể mở một như là chỉ đọc này sẽ cho phép có không phải là một vấn đề tương tranh như đọc được đảm bảo để được thread an toàn. This article nên giải thích cách thực hiện những gì tôi đã đề xuất

+0

Tôi đang mở tệp từ C# ở chế độ Chỉ đọc. Nhưng tôi vẫn nhận được ngoại lệ này. Điều gì có thể là vấn đề và làm thế nào tôi có thể giải quyết nó? –

0

Điều đó là không thể.

Một tệp có thể được mở bằng loại bảo vệ khác. Excel sẽ mở tệp độc quyền, với mục đích bảo vệ tệp khỏi bị thay đổi bởi một số chương trình khác và sau đó được hoàn nguyên khi Excel lưu tệp.

Excel có thể đã mở tệp và cho phép đọc, nhưng sau đó bạn có thể kết thúc trong tình huống bế tắc khi hai ứng dụng có tệp mở để đọc và không thể lưu bất kỳ thứ gì vào đó.

+0

Điều đó dường như không phải là trường hợp dựa trên liên kết tôi đã cung cấp. – Woot4Moo

+0

@ Woot4Moo: Bài viết đó về việc mở một bảng tính chứ không phải tệp CSV và mở tệp để truy cập chỉ đọc, không mở tệp đã được mở riêng, vì vậy tôi xin lỗi nhưng không liên quan gì cả. – Guffa

+0

thực sự nó khá liên quan. Nếu OP xem xét thứ tự các tập tin được mở, bạn có thể mở Excel trước tiên như là một thể hiện chỉ đọc có khả năng giảm thiểu vấn đề – Woot4Moo

7

Có thể nhưng bạn phải kiểm soát cẩn thận việc chia sẻ tệp bạn chỉ định. Hầu hết các lớp .NET mặc định là FileShare.Read, từ chối một tiến trình khác từ việc ghi vào tập tin. Nhưng điều đó không thể hoạt động nếu tệp được Excel mở ra, nó đã giành được quyền ghi vào nó. Bạn không thể phủ nhận quyền đã được mua lại.

Để khắc phục vấn đề này, làm cho mã của bạn trông tương tự như sau:

 using (var fs = new FileStream(@"c:\\temp\\test.csv", FileMode.Open, 
        FileAccess.Read, FileShare.ReadWrite)) 
     using (var sr = new StreamReader(fs)) { 
      // Read it... 
     } 

Lưu ý việc sử dụng FileShare.ReadWrite. Tôi đã xác minh mã này hoạt động trong khi Excel đã test.csv được mở.

Hãy coi chừng sự cố tiềm ẩn bạn sẽ mời với điều này, những điều kỳ quặc có thể xảy ra khi Excel ghi vào tệp ngay khi bạn đang đọc. Bạn có thể đọc rác, một phần dữ liệu cũ, một phần của dữ liệu mới, không có cách nào tốt để chẩn đoán điều này.

0

Một giải pháp khác, được đề xuất bởi this answer, là sao chép tệp vào tệp tạm thời và mở tệp đó.

Sử dụng

System.IO.File.Copy(sourcepath, copypath, false); 
Các vấn đề liên quan