2012-10-30 51 views
10

我有一個非常大的字符數組,我需要轉換爲字符串,以使用正則表達式就可以了。
但它是如此之大,我得到OutOfMemoryException當我傳遞字符串構造函數。如何從char數組創建一個字符串而不復制它?

我知道,字符串是不可變的因此不應該可以指定其底層字符集合,但我需要一種方法來使用的正則表達式,而不復制整個事情。

我如何獲得該數組?

  • 我從文件中使用StreamReader得到它。我所知道的起始位置和內容閱讀的長度,ReadReadBlock方法需要我提供一個緩衝char[]

所以這裏是我想知道的事情:

  • 是否有指定字符串的墊層收集的方法嗎? (難道它甚至保持其字符數組中的?)
  • ...或者直接字符數組上使用正則表達式?
  • ...或者直接獲取文件的一部分字符串?
+2

什麼是正則表達式?如果它足夠簡單,你可以用代碼遍歷'char []'來代替它。 –

+0

'char []'有多大? –

+0

@Matt:不幸的是我不能。這是一個非常漫長而複雜的解析器。 –

回答

1

我想你最好的選擇是將多個char []塊讀入與某個維度重疊的單個字符串。通過這種方式,您可以在各個區塊上執行您的正則表達式,並且重疊會爲您提供確保區塊中的「中斷」不會中斷搜索模式的功能。在僞碼的方式:

int chunkSize = 100000; 
int overLap = 2000; 

for(int i = 0; i < myCharArray.length; i += chunkSize - overlap) 
{ 
    // Grab your array chunk into a partial string 
    // By having your iteration slightly smaller than 
    // your chunk size you guarantee not to miss any 
    // character groupings. You just need to make sure 
    // your overlap is sufficient to cover the expression 
    string chunk = new String(myCharArray.Skip(i).Take(chunkSize).ToArray()); 
    // run your regex 
} 
+1

評論:沒有理由使用Linq方法'跳過「和」跳轉「。有[字符串構造函數重載](http://msdn.microsoft.com/en-us/library/ms131424.aspx)做這樣的東西。此外,Linq方法'ToArray()'會複製數據一段時間。 –

+0

+1。用重疊的塊閱讀似乎是在C#中與未知正則表達式匹配的合理方法。評論評論:我認爲可以使用Skip/Take樣本,因爲它很好地表明瞭這一點,而且明顯錯誤的做法不太可能直接用作複製粘貼。 –

+0

@JeppeStigNielsen:這只是爲了僞代碼,而不是查找最好的c#方法,我用我定期輸入的東西去找到我的觀點。如果有人逐字執行上述代碼,我會質疑他們的理智。 –

-1

如果您使用的是.NET 4.0或更高版本,你應該使用什麼是MemoryMappedFile。這個類是專門設計的,所以你可以操縱非常大的文件。從MSDN文檔:

內存映射文件的文件的內容映射到應用程序的 邏輯地址 空間。內存映射文件使程序員非常大的文件工作,因爲 內存可以同時管理,並允許他們無需爲尋求完整,隨機訪問文件 。內存映射文件也可以通過多個 進程共享。

一旦獲得了內存映射文件,請查看this Stack Overflow answer瞭解如何將RegEx應用於內存映射文件。

希望這會有所幫助!

+0

-1。不知道爲什麼使用MemoryMappedFile比StreamReader更好(必須手動處理編碼)......也不清楚爲了在字節數組上運行Regex而在Java代碼中實現匹配的C#實現。 –

+0

@AlexeiLevenkov - MemoryMappedFile比StreamReader更好,因爲StreamReader會將整個文件讀入內存。 MemoryMappedFile將文件分割成窗口或視圖,使您可以在文件的特定區域上進行操作。 MemoryMappedFile只讀入所需的字節數量,而不是整個事物。 – Icemanind

+4

@icemanind:錯了。 StreamReader不會將整個文件讀入內存。 – SLaks

1

一個比較難看的選擇是使用非託管的正則表達式庫(如POSIX正則表達式庫)和不安全的代碼。你可以獲得一個byte *指向char數組的指針並將其直接傳遞給非託管庫,然後將響應編組回去。

fixed (byte * pArray = largeCharArray) 
{ 
    // call unmanaged code with pArray 
} 
1

如果你有,你可以搜索以保證不會在你試圖找到模式的字符或圖案,你可以掃描該字符數組,創建更小的字符串單獨處理。過程將是這樣的:

char token = '|'; 
int start = 0; 
int length = 0; 
for(int i = 0; i < charArray.Length; i++;) 
{ 
    if(charArray[i] == token) 
    { 
     string split = new string(charArray,start,length); 
     // check the string using the regex 

     // reset the length 
     length = 0; 
    } 
    else 
    { 
     length++; 
    } 
} 

這樣你就可以複製在每次嘗試後對整個字符串進行GCed的字符串的較小部分。

相關問題