2012-08-27 4 views
34

저는 C#에서 많은 문자열 조작을하고 있으며 실제로 문자열 당 1 바이트를 저장해야합니다. 이것은 메모리에서 동시에 기가 바이트의 텍스트가 필요하고 메모리 문제가 적기 때문입니다. 필자는이 텍스트가 비 ASCII 문자를 절대로 포함하지 않는다는 것을 알고 있습니다. 따라서 실제로 System.String과 System.Char가 문자 당 2 바이트로 모든 것을 저장한다는 사실은 불필요하고 실제적인 문제입니다.C#에서 UTF8로 문자열 저장하기

CharAscii 및 StringAscii 클래스를 코딩하려고합니다. 문자열은 기본적으로 데이터를 byte []로 유지하고 System.String에서 수행하는 것과 유사한 문자열 조작 방법을 제공합니다. 그러나 이것은 매우 표준적인 문제인 것처럼 보이는 많은 일을하는 것처럼 보입니다. 그래서 저는 이미 여기에 더 쉬운 해결책이 없다는 것을 확인하기 위해 정말로 게시하고 있습니다. 예를 들어, System.String이 내부적으로 데이터를 UTF8로 저장하도록 만들 수있는 방법이 있습니까? 예를 들어 눈치 채지 못했거나 다른 방법으로 문제를 해결할 수 있습니까?

+0

.NET이 가장 좋은 방법입니까? 그것은 C/C++ 메모리에서 거대한 문자열의 조작을위한 더 나은 옵션이 될 것 같습니다. –

+4

Jon Skeet이 작년에 조사했습니다. http://msmvps.com/blogs/jon_skeet/archive/2011/04/05/of-memory-and-strings.aspx –

+0

[Somewhere] (http://msdn.microsoft.com) /en-us/library/windows/desktop/bb540816%28v=vs.85%29.aspx) utf8 문자열이 있습니다 – Gabber

답변

6

CLR은 문자 인코딩에 UTF-16을 사용합니다. 가장 좋은 방법은 인코딩 클래스 & BitConverter를 사용하여 텍스트를 처리하는 것입니다. 이 질문은 두 인코딩 사이의 변환을위한 좋은 사례가 있습니다 정말

Convert String (UTF-16) to UTF-8 in C#

+0

감사합니다. 링크에는 전환 수행에 대한 많은 정보가 포함되어 있으므로 답변으로 표시했습니다. 나는 당신과 KeithS가 제안한 접근 방식이 최대 성능과 구현에 너무 오래 걸리지 않고 메모리를 절약하는 일종의 솔루션을 얻는 것 사이에서 가장 좋은 절충안이라고 생각합니다. – PhantomDrummer

11

데이터를 UTF-8 바이트로 검색하고 필요에 따라 조각을 System.String으로 변환 한 다음 그 반대의 경우 문자열을 메모리로 다시 밀어 넣을 수있는 래퍼를 만들 수 있습니다. Encoding 클래스는 여기에서 당신을 도울 것입니다 :

var utf8 = Encoding.UTF8; 
byte[] utfBytes = utf8.GetBytes(myString); 

var myReturnedString = utf8.GetString(utfBytes); 
+0

+1, 부동산 회사의 대량 데이터를 수확 할 때이 문제를 직접 조사했습니다.이 솔루션은 조금 마법적이고 겉으로보기에는 janky가 C#으로 생각해 낼 수있는 가장 좋은 방법입니다. – tmesser

+0

이것은 결국 UTF-16으로 인코딩 된 문자열 개체로 끝납니다. – Tigran

+0

@Tigran, 언제든지 System.String을 사용하려고하면이를 피할 방법이 없습니다. 그러나 인코딩 된 바이트 배열의 하위 섹션을 꺼내 제어 된 방식으로 써낼 수 있습니다. 빨려 들어가는 리소스의 수에 대한 상한선은 남겨 둡니다. – tmesser

2

하지 않습니다. System.String은 문자열을 저장하도록 설계되었습니다. 귀하의 요구 사항은 특정 메모리 이점을 지닌 매우 특별한 문자열 집합입니다.

이제 "특정 메모리 이점을 지닌 문자열의 매우 특별한 하위 집합"이 많이 등장하지만 항상 동일한 특정 하위 집합과 같지는 않습니다. ASCII 전용 코드는 사람이 읽을 수있는 코드가 아니므로 짧은 코드 또는 스트림 처리 방식으로 처리 할 수있는 코드이거나 다른 작업을 수행하는 바이트로 병합 된 텍스트 청크가 될 수 있습니다 (예를 들어 꽤 많은 바이너리 형식은 ASCII로 직접 번역되는 작은 비트를가집니다).

이와 같이, 당신은 꽤 이상한 요구 사항을 가지고 있습니다.

기가 바이트 부분에 올 때 더욱 그렇습니다. 제가 공연을 다루고 있다면, 저는 어떻게 공연을 다룰 필요가 없으며, 단지 50 %가 아닌 훨씬 더 심각한 저축을 얻는 방법을 생각하고 있습니다. 나는 현재 파일에 관심이 없거나 밧줄에 관한 덩어리 나 다른 것들에 대해 생각할 것입니다. 물론 이러한 것들이 모든 경우가 아닌 어떤 경우에는 작동 할 것입니다. 다시 한번 말하면, 우리는 .NET이 무언가에 꼭 맞아야하는 것을 말하는 것이 아닙니다. 하나의 크기가 적합하지 않기 때문입니다. 모든.

그 외에도 utf-8 비트는 그다지 어렵지 않습니다. 그것은 작업이되는 다른 모든 방법입니다. 다시, 당신이 거기에서 필요로하는 것은 다른 누군가와 같지 않을 것입니다.

+3

그것은 그렇게 이상하지 않습니다. OP는'System.String'과 같은 방식으로 작동하는 문자열을 원하지만 절반의 공간을 차지합니다. 드롭 인 대체, 즉 –

+0

@RobertHarvey 예, 그렇습니다. O (n) 길이를 원하지 않을 것입니다. 왜냐하면 그들이 데이터에 대한 지식을 필요로하지 않는다는 것을 알고 있기 때문입니다. utf-8 기반 문자열과 비슷하지만 동일하지 않은 사람은 ASCII 전용으로 붙지 않기 때문에 O (n) 카운트가 필요합니다. 일반적인 문제는 많이 발생하지만 작은 세부 사항이 다르므로 한 사람이 다른 사람의 독약을 대체 할 수 있습니다. –

+0

로버트 하비가 정확히 가지고 있습니다. Jon - 내가하고있는 일은 매우 대략적으로 텍스트 사이에 광범위한 상호 참조가 필요합니다. 따라서 처리하는 동안 전체 텍스트가 메모리에 저장되는 것을 피하는 것은 매우 어려울 것입니다. 덩어리 쓰기 나는 즉시 파일에 관심이 없기 때문에 나중에 밀리 세컨드를 읽어야한다. 나는 성능이 무서울 것이라고 생각한다. (코드를 복잡하게 만드는 것뿐만 아니라) – PhantomDrummer

1

내가 볼 수 있듯이 C#의 char은 1 대신 2 바이트를 차지합니다.

System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open); 
    System.IO.BinaryReader br = new System.IO.BinaryReader(fs); 

    byte[] buffer = new byte[1024]; 
    int read = br.Read(buffer, 0, (int)fs.Length); 

    br.Close(); 
    fs.Close(); 

그리고 당신은 파일에서 바이트를 읽고있는이 방법 : 텍스트 파일을 읽을 수

한 가지 방법은 그것을 열 수 있습니다. * 함께 사용해 보았습니다.TXT 파일 UTF-8 문자당 1 바이트 ANSI2 문자 당 바이트, 으로 인코딩.

+0

UTF-16을 의미합니까? UTF-8은 ANSI와 마찬가지로 요청하는 특정 데이터에 대해 char 당 1 바이트가됩니다. 하지만 고마워, 실제로 이것이 내가 데이터를 읽는 방법과 정확히 일치한다. – PhantomDrummer

+0

@PhantomDrummer 실제로 UTF-8, notepads 통상 인코딩을 시도해 보았습니다. char 당 2 바이트가 걸렸습니다. :) 기꺼이 도와 드리겠습니다. – Thanatos