2010-10-02 164 views
7

我正在C#中構建一個應用程序,在該應用程序中,我必須打開一個CSV文件才能從中讀取數據。當我嘗試從C#打開CSV文件時,當該文件已在Excel中打開時,我收到一個異常。例外說明該進程無法訪問該文件,因爲該文件已經打開。我怎樣才能解決這個問題,並打開文件,即使它在其他應用程序中打開?打開已打開文件的例外

謝謝, Rakesh。

+0

請張貼一些代碼來告訴我們你做了什麼至今 – Woot4Moo 2010-10-02 16:53:44

+1

這是代碼:使用(的FileStream FS =新的FileStream(csvOpenFileDialog.FileName,FileMode.Open,FileAccess.Read) ) – 2010-10-02 16:55:40

+0

你錯過了一個參數。閱讀我的答案。 – Nayan 2010-10-02 20:17:08

回答

7

我在一段時間後面臨這個問題。

您缺少FileShare參數。沒有指定,如果你打開一個文件,它將被你的應用程序鎖定。但由於它已被Excel(或任何其他應用程序)打開,您將收到一個異常。

您可以嘗試使用這個 - 我認爲這將是你最好的選擇 -

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

這個代碼表示:你好Excel中!如果您允許(閱讀,不拋出異常),我想閱讀該文件,但我不會嘗試擁有它,並且我知道您可以隨時修改它。

如果拋出錯誤,那麼Excel甚至拒絕讀取訪問權限。太糟糕了! 一切順利。

+2

我發現FileShare.Read沒有工作,而FileShare.ReadWrite did – 2011-12-15 10:48:44

+1

不知道你做了什麼,但是......它的好處 - 無論對你有用! – Nayan 2011-12-15 11:44:16

+0

使用FileShare.ReadWrite而不是FileShare.Read,如Hans所述。 – 2011-12-15 12:16:23

0

由於併發問題,您不能選擇寫入同一文件的兩個實例。應該可以以只讀方式打開一個,這樣可以避免出現併發問題,因爲讀取確保是線程安全的。 This article應該解釋如何做我建議的

+0

我正在以只讀模式從C#打開文件。但我仍然得到這個例外。可能是什麼問題,我該如何解決它? – 2010-10-02 16:54:02

0

這是不可能的。

可以使用不同類型的保護打開文件。 Excel專門打開文件,目的是保護文件不被其他程序改變,然後在Excel保存時恢復。

Excel可能已經打開文件並允許讀取,但是最終可能會導致死鎖情況,即兩個應用程序打開文件以供讀取,並且都不能保存任何文件。

+0

這似乎不是基於我提供的鏈接的情況。 – Woot4Moo 2010-10-02 17:00:58

+0

@ Woot4Moo:那篇文章是關於打開一個電子表格而不是CSV文件,以及打開文件進行只讀訪問,而不是打開一個已經打開的文件,所以我很抱歉,但它根本不相關。 – Guffa 2010-10-02 17:06:35

+0

其實它是非常相關的。如果OP查看打開文件的順序,您可以讓Excel首先打開文件作爲只讀實例,這可能會緩解問題 – Woot4Moo 2010-10-02 17:20:45

7

這是可能的,但你必須仔細控制你指定的文件共享。大多數.NET類默認爲FileShare.Read,拒絕寫入文件的另一個進程。但是,如果文件是由Excel打開的,那麼它就無法工作,它已經獲得對它的寫入權限。你不能否認已經獲得的權利。

要解決這個問題,使你的代碼類似於此:

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

的使用注意事項FileShare.ReadWrite的。我驗證了此代碼在Excel打開test.csv的情況下工作。

請注意您可能會遇到的潛在問題,而Excel在寫入文件時會發生奇怪的事情,就像您在閱讀時一樣。您可能會閱讀垃圾,是舊數據的一部分,是新的一部分,沒有一個好的診斷方法。

0

this answer建議的另一種解決方案是將文件複製到臨時文件並打開該文件。

使用

System.IO.File.Copy(sourcepath, copypath, false);