12

我有一个非常大的 char 数组,我需要将其转换为字符串才能在其上使用 Regex。但是当我将它传递给字符串构造函数时
,它太大了。OutOfMemoryException

我知道字符串是不可变的,因此它不应该指定它的底层字符集合,但我需要一种在不复制整个内容的情况下使用正则表达式的方法。

我如何获得该数组?

  • 我使用StreamReader. 我知道要读取的内容的起始位置和长度,Read方法ReadBlock需要我提供一个char[]缓冲区。

所以这里是我想知道的事情:

  • 有没有办法指定字符串的底层集合?(它甚至将其字符保存在数组中吗?)
  • ...或直接在字符数组上使用正则表达式?
  • ...或者直接将文件的一部分作为字符串获取?
4

4 回答 4

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++;
    }
}

这样,您将在每次尝试后复制较小的字符串片段,而不是整个字符串。

于 2012-10-31T13:22:06.753 回答
0

一个相当丑陋的选择是使用非托管 RegEx 库(如 POSIX 正则表达式库)和不安全的代码。您可以获得指向 char 数组的 byte * 指针并将其直接传递给非托管库,然后将响应编组返回。

fixed (byte * pArray = largeCharArray)
{
   // call unmanaged code with pArray
}
于 2012-10-30T21:07:38.700 回答
0

我认为您最好的选择是将多个 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
}
于 2012-10-30T19:55:06.503 回答
-2

如果您使用的是 .NET 4.0 或更高版本,您应该使用的是MemoryMappedFile。此类是专门设计的,因此您可以操作非常大的文件。从 MSDN 文档:

内存映射文件将文件的内容映射到应用程序的逻辑地址空间。内存映射文件使程序员能够处理非常大的文件,因为内存可以同时管理,并且它们允许对文件进行完全、随机的访问,而无需查找。内存映射文件也可以在多个进程之间共享。

获得内存映射文件后,请查看有关如何将 RegEx 应用于内存映射文件的Stack Overflow 答案。

希望这可以帮助!

于 2012-10-30T20:06:30.733 回答