2012-10-30 2 views
10

정규식을 사용하기 위해 문자열로 변환해야하는 매우 큰 문자 배열이 있습니다.
하지만 너무 커서 문자열 생성자에 전달하면 OutOfMemoryException이됩니다.문자 배열을 복사하지 않고 문자열을 만드는 방법은 무엇입니까?

는 그 문자열이 불변 따라서는 의 기본이되는 문자의 집합을 지정할 수 안하지만 전체를 복사하지 않고 그에 정규 표현식을 사용하는 방법이 필요합니다 알고 있습니다.

어떻게 배열을 얻을 수 있습니까?

  • StreamReader을 사용하여 파일에서 가져옵니다. 나는 시작 위치와 읽을 내용의 길이를 알아, ReadReadBlock 방법은 내가 char[] 버퍼를 제공해야합니다.

    • 문자열의 기저의 콜렉션을 지정하는 방법이 있나요 :

    그래서 여기에 내가 알고 싶은 것들? (심지어 문자 배열을 유지합니까?)

  • ... 또는 문자 배열에서 Regex를 직접 사용 하시겠습니까?
  • ... 또는 파일의 일부를 문자열로 직접 가져 오는 중입니까?
+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 메소드를 사용할 이유가 없습니다. Skip'과'Take'. 이와 같은 작업을 수행하려면 [문자열 생성자의 오버로드] (http://msdn.microsoft.com/en-us/library/ms131424.aspx)가 있습니다. 또한, Linq 메소드'ToArray()'는 데이터를 추가로 복사합니다. –

+0

+1. 중복 된 덩어리를 읽는 것은 C#에서 알 수없는 정규식과 일치시키기위한 합리적인 접근 방법 인 것 같습니다. 코멘트에 대한 의견 : 샘플을 의도적으로 보여 주므로 Skip/Take를 사용하는 것이 좋습니다. 분명히 잘못된 일은 복사하여 붙여 넣기로 직접 사용하지 않을 것입니다. –

+0

@JeppeStigNielsen : 방금 Psuedo-Code가 될 의도 였고 정기적으로 타이핑할만한 최고의 C# 메소드를 찾는 것이 아니라 요점을 지적했습니다. 누군가 위의 코드를 그대로 구현한다면 나는 그들의 정신을 의심 할 것이다. –

-1

당신이 .NET 4.0 이상을 사용하는 경우, 당신이해야 무엇 사용은 MemoryMappedFile이다. 이 클래스는 매우 큰 파일을 조작 할 수 있도록 독점적으로 설계되었습니다. MSDN 설명서에서 :

메모리 매핑 된 파일은 응용 프로그램의 논리 주소 공간에 파일의 내용을 매핑합니다. 메모리 매핑 파일을 사용하면 프로그래머는 메모리를 동시에 관리 할 수 ​​있으므로 매우 큰 파일을 처리 할 수 ​​있으며 검색 할 필요없이 파일에 대한 완전 무작위 액세스를 허용합니다. 메모리 매핑 된 파일은 여러 프로세스에서 공유 할 수도 있습니다.

메모리 매핑 된 파일을 얻은 후 메모리 매핑 된 파일에 RegEx를 적용하는 방법을 확인하려면 this Stack Overflow answer을 확인하십시오.

희망이 도움이됩니다.

+0

-1. MemoryMappedFile을 사용하는 것이 StreamReader보다 나은 이유는 확실하지 않습니다. (수동으로 인코딩을 처리해야 할 것입니다 ...) 바이트 배열에서 Regex를 실행하기위한 Java 코드와 일치하는 C# 구현을 가져올 위치가 명확하지 않습니다. –

+0

@AlexeiLevenkov - StreamReader가 전체 파일을 메모리로 읽으므로 MemoryMappedFile이 StreamReader보다 좋습니다. MemoryMappedFile은 파일의 특정 영역을 조작 할 수있는 창이나보기로 파일을 분할합니다. MemoryMappedFile은 전체가 아니라 필요한 바이트 수만 읽습니다. – Icemanind

+4

@ 매스컴 : 틀렸어. StreamReader는 전체 파일을 메모리로 읽지 않습니다. – SLaks

1

하나의보기 흉한 옵션은 관리되지 않는 RegEx 라이브러리 (예 : POSIX 정규식 라이브러리)와 안전하지 않은 코드를 사용하는 것입니다. 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 될 것이라고 문자열의 작은 세그먼트를 복사하는 그런 식으로.

관련 문제