2010-02-06 8 views
2

줄 단위로 읽으려는 문자열이 있지만 줄 바꿈 문자가 있어야합니다 (StringReader.ReadLine이 불행히도 다듬어지지 않습니다. 루비에서 보관됩니다). 이 작업을 수행하는 가장 빠르고 가장 효과적인 방법은 무엇입니까? 입력을 문자 단위 읽기줄 바꿈 문자를 자르지 않고 C#에서 한 줄 읽음

  • 과 긍정적 예측
와 RegExp.Split를 사용 할 때마다
  • 구분 선 검사 :

    대안 나는 대해 생각해 봤는데

    또는 줄의 실제 위치를 알아야하기 때문에 줄 구분 기호 만 신경 써야하며 구분 기호는 한 문자 또는 세 문자 일 수 있습니다. 따라서 문자열 내에서 커서의 실제 위치를 되돌릴 수 있다면 StringReader에도이 기능이 없습니다.

    편집 : 여기 현재 구현됩니다. 파일 끝은 빈. 자열을 리턴하여 지정됩니다.

    StringBuilder line = new StringBuilder(); 
    int r = _input.Read(); 
    while (r >= 0) 
    { 
        char c = Convert.ToChar(r); 
        line.Append(c); 
        if (c == '\n') break; 
        if (c == '\r') 
        { 
        int peek = _input.Peek(); 
        if (peek == -1) break; 
        if (Convert.ToChar(peek) != '\n') break; 
        } 
        r = _input.Read(); 
    } 
    return line.ToString(); 
    
  • +0

    내 대답에 다른 대안이있을 수 있습니다,하지만 데이터에서 오는되는 위치에 따라 달라 소스 단지 일반 문자열이 어떤 종류의 스트림, 또는인가? – Aaronaught

    +0

    나는 그것들이 일관성이 없을 것이라고 확신하며 입력을 변경할 수 없다. 그것은 읽기 전용으로 간주된다 (원래의 문자열 안에 문자 위치가 필요하기 때문에 문자열을 복제하고 변경하지 않는다). 그러나 입력은 일반 문자열입니다. – SztupY

    +0

    아래의 Aaronaught에 대한 귀하의 의견에서 "모노와 .net2와 호환되도록 설계되었으므로 가정 할 수 없습니다": 주어진 유일한 줄 수있는 줄 끝 부분에 대한 유효한 가정은 없는가? 파싱하는 문자열의 소스? – BillW

    답변

    2

    파일 간의 불일치가 우려됩니까 (예 : Unix/Mac vs. Windows) 또는 파일 내에 있습니까?

    개개의 파일이 과 일치하는 것으로 알고 있다면 아주 쉽게 최적화 할 수 있습니다.은 첫 번째 줄을 문자로만 읽고 해당 구분 기호가 무엇인지 파악하는 것입니다. 그런 다음 다른 라인의 정확한 위치를 결정하는 것은 간단한 수학 일 것입니다.

    실패하면 캐릭터 대가로가는 것이 좋을 것 같습니다. 정규식은 너무 "똑똑한 것 같습니다." 이것은 복잡한 기능처럼 들리며, 가장 중요한 것은 디버깅, 읽기, 이해, 그리고 가장 중요한 디버깅을 쉽게하는 것이라고 생각합니다.


    다른 방법으로 데이터 소스가 스트림 인 경우 더 효율적입니다. 불행히도 그것은 귀하의 코멘트에서 언급 한대로, 그래서 당신이 먼저 만들어야 할 것; 하지만 어쨌든 솔루션을 포함 시키면 다음과 같은 영감을 얻을 수 있습니다.

    public IEnumerable<int> GetLineStartIndices(string s) 
    { 
        yield return 0; 
        byte[] chars = Encoding.UTF8.GetBytes(s); 
        using (MemoryStream stream = new MemoryStream(chars)) 
        { 
         using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) 
         { 
          while (reader.ReadLine() != null) 
          { 
           yield return stream.Position; 
          } 
         } 
        } 
    } 
    

    이렇게하면 줄 바꿈마다 시작 위치가 다시 표시됩니다. 분명히 당신은 당신이 필요로하는 무엇이든을하기 위하여 이것을 비틀어서 좋, ie 당신이 읽는 실제적인 선을 가진 다른 무언가를하십시오.

    바이트 배열을 만들기 위해 문자열 복사본을 만들어야하므로 매우 큰 문자열에는 적합하지 않습니다. char-by-char 접근법보다 약간 좋지만, 버그가 발생하기 쉽지 않아 문자열이 메가 바이트가 아닌 경우 고려할 가치가 있습니다.

    +0

    모노 및 .net2와 호환되도록 고안된 라이브러리의 일부입니다. 실수는 없어야하므로 가정 할 수 없습니다. – SztupY

    0

    위치 만 신경 쓰는 경우 : ReadLine() 다음 행으로 이동합니다. 스트림의 .Position을 아래에 저장하면 ReadLine() 다음에 .Position과 비교할 수 있습니다. 그것은 방금 읽은 문자열의 길이입니다. 더하기 구분 기호입니다. 구분 기호의 길이는 currentPosition - previousPosition - line.Length입니다.

    이렇게하면 1 또는 2 바이트인지 쉽게 알 수 있습니다 (세부 정보는 알지 못하지만 어쨌든 위치 만 신경 썼다고 말함).

    +0

    .NET의 StringReader에서 스트림을 가져올 수 있습니까? 나는 문서에있는 적절한 함수를 보지 못했다. – SztupY

    +0

    Urgs. 그렇지 않습니다. Pardon은 독자의 "String"부분을 놓쳤으며 스트림을 StreamReader에 전달한다고 가정했습니다. 그렇게 할 수 있다면 내 제안이 효과가 있고 원하는대로 할 수 있습니다. 네가 그렇게 할 수 없다면 쓸모없는 쓰레기 야. 그냥 지울 수있어. –

    +0

    Aaronaught가 자세를 취하는 방법을 확인하고 도움이 될 수있는 방법을 이해하기 위해 제 제안을 살펴보십시오. (tm) 트릭을해야할까요? –

    0

    File.ReadAllText는 모든 파일 내용을 가져옵니다. 예. 모든. 따라서 사용하기 전에 파일 크기를 확인하는 것이 좋습니다.

    편집 :

    다음 라인으로 라인을 산출하는 열거를 생성에 다 읽었다.

    foreach(string line in Read("some.file")) 
    { ... } 
    
    
    private IEnumerator Read(string file) 
    { 
        string buffer = File.ReadAllText() 
        for (int index=0;index<buffer.length;index++) 
        { 
         string line = ... logic to build a "line" here 
         yield return line; 
        } 
    
        yield break; 
    
    } 
    
    +0

    그는 입력이 이미 문자열이기 때문에 아마도 메모리에 맞다고 말합니다. – Aaronaught

    +0

    그리고 한 줄씩 처리해야하므로 모든 내용을 읽는 것이 필요 없습니다. – SztupY

    0
     FileStream fs = new FileStream("E:\\hh.txt", FileMode.Open, FileAccess.Read); 
         BinaryReader read = new BinaryReader(fs); 
         byte[] ch = read.ReadBytes((int)fs.Length); 
         byte[] che=new byte[(int)fs.Length]; 
         int size = (int)fs.Length,j=0; 
         for (int i =0; i <= (size-1); i++) 
         { 
          if (ch[i] != '|') 
          { 
           che[j] = ch[i]; 
           j++; 
          } 
    
         } 
         richTextBox1.Text = Encoding.ASCII.GetString(che); 
         read.Close(); 
         fs.Close();