2012-10-05 23 views
12

如何在沒有出現IO異常的情況下將在Excel中打開的文本文件的所有行讀入string[]如何在Excel中打開的文件上執行File.ReadAllLines?

有這個問題,這可能是答案的一部分,雖然我不知道我怎麼會用什麼在那裏: How do I open an already opened file with a .net StreamReader?

+0

什麼不明白你鏈接到的答案?這很清楚。你試過了嗎?向我們顯示您的代碼。 – Polyfun

+0

我該怎麼處理這段代碼,以便用文本文件的行填充我的'string []行'?這裏沒有關於它的信息。 – user1306322

+0

http://stackoverflow.com/questions/3560651/whats-the-least-invasive-way-to-read-a-locked-file-in-c-sharp-orhaps-in-unsaf – m0s

回答

30

你的問題是Excel打開文件作爲讀/寫。 File.ReadAllLines()在打開其他應用程序時無法訪問該文件。如果您以只讀方式在Excel中打開csv,則不會遇到此異常。

這是因爲.Net中的實現不會打開具有適當權限的內部流,以便在另一個應用程序擁有對其的寫入權限時訪問該文件。

所以這裏的修復很簡單,編寫你自己的ReadAllLines()方法,在啓動基礎Stream時設置適當的權限。

下面是從什麼ReadAllLines()確實對自己大量借鑑了一個想法:

public string[] WriteSafeReadAllLines(String path) 
{ 
    using (var csv = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    using (var sr = new StreamReader(csv)) 
    { 
     List<string> file = new List<string>(); 
     while (!sr.EndOfStream) 
     { 
      file.Add(sr.ReadLine()); 
     } 

     return file.ToArray(); 
    } 
} 

這之間唯一的區別是什麼ReadAllLines確實是FileShare權限設置爲FileShare.ReadWrite,這使得要打開的文件即使它在另一個應用程序中以讀/寫權限打開。

現在,您必須瞭解可能由此產生的問題,因爲其他應用程序對該文件具有寫入權限,因此可能會出現複雜情況。

  1. 您將要讀取文件的最後一次保存的版本,所以如果你有在Excel中未保存的更改,這種方法將無法讀取它們
  2. 如果您將文件保存在Excel中,而這種方法是閱讀它的中間,你可能會根據具體情況得到一個例外。這是因爲該文件在保存時被完全鎖定,因此如果您在鎖定文件時嘗試讀取該文件,將會拋出一個System.IO.IOException
  3. 如果您保存文件並設法避免發生異常(極不可能,但在給定特定時間的情況下可能),您將讀取新保存的文件,而不是原始文件。

要了解爲什麼你不能讀取文件時,它是開放供其他應用程序寫作,你要看看在.NET中的實際執行。 (這是在.Net 4.5中的實現,因此如果您正在查看.Net的差異版本,它可能會稍有不同)。

這是File.ReadAllLines()實際上看起來像:所以在這裏我們來爲什麼例外是拋出,當原因

internal StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool checkHost) 
{ 
    if (path == null || encoding == null) 
    throw new ArgumentNullException(path == null ? "path" : "encoding"); 
    if (path.Length == 0) 
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); 
    if (bufferSize <= 0) 
    throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
    this.Init((Stream) new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost), encoding, detectEncodingFromByteOrderMarks, bufferSize, false); 
} 

public static string[] ReadAllLines(string path) 
{ 
    if (path == null) 
    throw new ArgumentNullException("path"); 
    if (path.Length == 0) 
    throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); 
    else 
    return File.InternalReadAllLines(path, Encoding.UTF8); 
} 


private static string[] InternalReadAllLines(string path, Encoding encoding) 
{ 
    List<string> list = new List<string>(); 
    using (StreamReader streamReader = new StreamReader(path, encoding)) 
    { 
    string str; 
    while ((str = streamReader.ReadLine()) != null) 
     list.Add(str); 
    } 
    return list.ToArray(); 
} 

在什麼StreamReader偷看在內部做隨路徑提供,StreamReader會創建一個FileStream,該參數的FileShare參數設置爲Read。這意味着它不能與具有對該文件的讀/寫訪問的另一個應用程序共享文件。要覆蓋此行爲,您需要爲其提供一個Stream,使用FileShare的不同設置,這是我在上面提供的解決方案中所做的。

+0

這很有意義,我相信它現在可以工作。 – user1306322

+0

@ user1306322它爲我工作。我剛剛遇到同樣的問題,閱讀了我在excel中打開的CSV文件,發現了您的問題,但不滿意答案,所以這就是我解決這個問題的方法。所以,如果你有任何複雜的問題,(除了我提到的),讓我知道。 – psubsee2003

1

試試這個。

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, 
System.IO.FileShare.ReadWrite) 
+2

我該如何做'string [] lines = something.ReadAllLines(myPath)'? – user1306322

+0

我不確定是否需要文件流來讀取文本文件中的行。有沒有其他方法可以做到這一點? – user1306322

1

只有在讀取限制打開文件時才能打開文件。否則,包括ReadAllLines在內的所有方法都可以正常工作而不會拋出許可異常。

相關問題