2012-08-06 501 views
7

我正在通過FileStream更改文件(這是一個非常大的文件,我只需要在不重寫整個文件的情況下更改標頭)如何檢測文件是否有Unix換行符( n)或Windows換行符( r n)?

該文件可以具有Unix或Windows換行符,對我來說很重要,以便我可以在更新文件時將正確的換行符寫回文件中。

我可以編寫一個簡單的函數,使用FileStream以塊的形式讀取文件並檢查換行字符

但是這個問題在之前必須解決,如果不是在C#那麼在Win32 API中呢?

什麼是檢測文件的換行樣式的最有效方法?

+0

不確定,因此評論,但它可能會使用正則表達式,如:'\ r \ n $'?這將檢查換行以'\ r \ n'結尾。如果沒有,那麼它必須是Unix系列。 – npinti 2012-08-06 13:51:15

+0

不可能,因爲使用.Net框架文件訪問對象上的任何「ReadLine」方法去除換行符。如果你不關心一個文件使用的是什麼樣的換行樣式,它們是很好的。如果我將文件作爲流讀取,我可以按照您的建議進行操作(基本上相當於我可能採取的方法..) – freshr 2012-08-06 14:03:30

+0

您能保證文件中的所有行結束符都是一致的嗎?從技術上講,在同一個文件中可能會有不同的混合行結束符。 – 2012-08-06 14:53:20

回答

2

非常感謝您的建議。我很驚訝沒有找到容易重用的東西,所以我創建了一個簡單的函數,我將它包含在這裏。請注意,它只是找到第一個換行符(\ n或\ r \ n)並將其作爲匹配返回。足夠滿足我的需求,但可能不夠健壯。

public bool TryDetectNewLine(string path, out string newLine) 
    { 
     using (var fileStream = File.OpenRead(path)) 
     { 
      char prevChar = '\0'; 

      // Read the first 4000 characters to try and find a newline 
      for (int i = 0; i < 4000; i++) 
      { 
       int b; 
       if ((b = fileStream.ReadByte()) == -1) break; 

       char curChar = (char)b; 

       if (curChar == '\n') 
       { 
        newLine = prevChar == '\r' ? "\r\n" : "\n"; 
        return true; 
       } 

       prevChar = curChar; 
      } 

      // Returning false means could not determine linefeed convention 
      newLine = Environment.NewLine; 
      return false; 
     } 
    } 
2

不幸的是,如果是Unix或DOS文件,我不認爲有一種方法可以100%確定,因爲大多數編輯器在打開/保存時沒有糾正錯誤結尾的文件。

我會讀取該文件作爲流和搜索的「\ r \ n」個出現的,只有「\ n」

使用一個簡單的統計分析(即哪一個具有最高的命中計數)的搜索結果可能會給你正確的答案。如果文件很大,那麼讀取文件的第一個X%就足夠了。

更簡單的解決方案當然是只搜索「\ r \ n」,如果找到,則假定它是DOS文件。如果文件是機器生成的,這應該工作到100%。

至於.NET Framework/WinAPI中的任何現有代碼,我還沒有看到任何執行此操作的代碼。

3

按照規定,如果不打開文本文件並通過字節流式傳輸,確實無法對文本文件的內容進行設置。如果您使用http下載文件,您可能會遇到麻煩,您可能會獲得一種MIME類型來表示文件類型,但通常它只是「八位字節流」。當你可以蠻橫強迫它,直到你找到一個換行符(「\ n」),然後備份一個字符,看看是否有回車符(「\ r」),我會採取更加平等的態度因爲你必須以任何方式讀取數據。

1)選擇要讀取的字節的樣本大小,應該從文件中獲取至少2或3條記錄。

2)將每個字節的遭遇(我把這個單字節字符集設置在這裏)存儲爲直方圖。您可以通過將計數存儲在由字節值索引的模式中來完成此操作,也可以使用字典。

3)看看回車和換行值計數。如果您有換行計數並且沒有回車,那麼它是一個unix文件。如果carraige返回和換行計數,那麼它是一個Windows文件。

這種方法還允許您執行的操作是對入站文件進行質量檢查。你有沒有aplha數字直方圖charcaters?然後有人向你傳遞了一個二進制文件。期待所有大寫?然後在upercase字符外尋找計數。有很多檢查可以避免處理非文本文件。

+1

你和@ Per的解決方案都假設所有的行結束符都是一致的,在野外,從技術上來說很可能有混合行結束標記。 – 2012-08-06 14:48:16

+2

沒錯,但是這裏的練習是假設file is unix or windows。我假設入站文件是一種格式,或者是因爲問題中提到的內容,如果一個預期的混合LF&CR/LF終止記錄,那麼它可能無關緊要行被終止。 – user957902 2012-08-06 14:58:46

相關問題