2011-09-29 1 views
3

Random.txt에서 5 번째 문자를 읽는이 작은 프로그램을 작성했습니다. random.txt에 한 줄의 텍스트가 있습니다. ABCDEFGHIJKLMNOPRST. 내가 예상 결과를 얻었다 : (A)의StreamReader.EndOfStream 속성이 BaseStream.Position 값을 변경하는 이유

  • 위치가 0
  • F의
  • 위치는 K의 5
  • 위치가 P의 10
  • 위치는 여기에 15

인 임 코드 :

static void Main(string[] args) 
{ 
    StreamReader fp; 
    int n; 
    fp = new StreamReader("d:\\RANDOM.txt"); 
    long previousBSposition = fp.BaseStream.Position; 
    //In this point BaseStream.Position is 0, as expected 
    n = 0; 

    while (!fp.EndOfStream) 
    { 
     //After !fp.EndOfStream were executed, BaseStream.Position is changed to 19, 
     //so I have to reset it to a previous position :S 
     fp.BaseStream.Seek(previousBSposition, SeekOrigin.Begin); 
     Console.WriteLine("Position of " + Convert.ToChar(fp.Read()) + " is " + fp.BaseStream.Position); 
     n = n + 5; 
     fp.DiscardBufferedData(); 
     fp.BaseStream.Seek(n, SeekOrigin.Begin); 
     previousBSposition = fp.BaseStream.Position; 
    } 
} 

내 질문은 이유가 무엇입니까? while (!fp.EndOfStream)BaseStream.Position은 19로 변경됩니다. BaseStream 끝. 나는 BaseStream.PositionEndOfStream에 전화 할 때 똑같이 체재 할 것이라는 점을 명백하게 틀리게 예상했다?

감사합니다.

+3

StreamReader에는 바이트를 텍스트로 디코딩 할 수있는 내부 버퍼가 있습니다. 그 메소드를 사용하면 (자), 파일 스트림로부터 바이트를 slurp하게됩니다. 그것의 위치 가치는 예측할 수 없을 것입니다. –

+0

@HansPassant, 나는 이것이 게시 된 코드에서'DiscardBufferedData()'를 호출하는 이유라고 생각한다. – svick

+0

@HansPassant, 네, 위의 코드로 놀았습니다. 그리고 StreamReader의 Read() 메서드로 인해 상황에 따라 BaseStream.Position이 변경되어 예측할 수없는 것으로 나타났습니다. – vldmrrdjcc

답변

4

THRE 특정 방법은 실제로 뭔가를 읽고 반환 값이 0 (StreamReader은 –가 내부 버퍼를 확인하는 또 다른 방법이 있는지 여부를 확인하는 것입니다,하지만 당신은 제대로 돈 그것은 DiscardBufferedData을 호출함으로써 가능합니다.)

그래서 EndOfStream은 기본 스트림에서 적어도 1 바이트를 읽어야합니다. 그리고 바이트 단위로 읽는 것이 비효율적이기 때문에 더 많이 읽습니다. 그것이 EndOfStream에 대한 호출이 위치를 끝으로 변경하는 이유입니다 (더 큰 파일의 경우 파일 끝이되지 않습니다).

바로 당신이 Stream (또는 특별히 FileStream)를 사용한다, 그래서 당신이 실제로, StreamReader를 사용할 필요가 없습니다 것 같다

using (Stream fp = new FileStream(@"d:\RANDOM.txt", FileMode.Open)) 
{ 
    int n = 0; 

    while (true) 
    { 
     int read = fp.ReadByte(); 
     if (read == -1) 
      break; 

     char c = (char)read; 
     Console.WriteLine("Position of {0} is {1}.", c, fp.Position); 
     n += 5; 
     fp.Position = n; 
    } 
} 

(I는 말 이상으로 위치를 설정 않습니다 모르겠어요 파일을이 상황에서 할 경우 체크를 추가해야 할 수도 있습니다.

+0

나는 이해한다고 생각한다. 한 가지 더 질문 : StreamReader는 전체 스트림을 버퍼링하지 않지만 일부 데이터는 버퍼링하지 않으므로 예측할 수없는 순간에 더 많은 데이터가 필요할 때 BaseStream에서 읽습니다. 알았어? – vldmrrdjcc

+0

예, 그렇습니다. 그것은 예측할 수있는 것을 제외하고는. 기본 스트림은 버퍼가 비어 있고 몇 바이트를 읽을 필요가있을 때마다 읽습니다. 특히 게시 한 코드에서는 버퍼를 버리기 전에 버퍼에서 읽지 않으므로. – svick

+0

EndOfStream은 정확히 다음 1024 바이트를 읽는 것 같습니다. EndOfStream 호출 후 DiscardBufferedData를 수행 한 다음 ReadLine을 사용하면 1024 자 이후의 행 부분을 가져옵니다. –

1

당신이 맞아요. 어쨌든 (MSDN: Read Text from a File)에 따라 StreamReader로 텍스트 파일을 읽는 올바른 방법은 다음과 같습니다 (이 방법은 항상 다음을 사용하여 스트림을 닫고 처리합니다. 블록)

try 
{ 
    // Create an instance of StreamReader to read from a file. 
    // The using statement also closes the StreamReader. 
    using (StreamReader sr = new StreamReader("TestFile.txt")) 
    { 
     String line; 
     // Read and display lines from the file until the end of 
     // the file is reached. 
     while ((line = sr.ReadLine()) != null) 
     { 
      Console.WriteLine(line); 
     } 
    } 
} 
catch (Exception e) 
{ 
    // Let the user know what went wrong. 
    Console.WriteLine("The file could not be read:"); 
    Console.WriteLine(e.Message); 
} 
+0

(! fp.EndOfStream) 동안 줄에 중단 점을 넣으면 BaseStream.Position이 해당 줄 바로 뒤, Console.WriteLine (... – vldmrrdjcc

+0

) 앞에 단순히 변경된다는 것을 알 수 있습니다. BaseStream.Position? –

+0

StreamReader에는 자신의 Position 속성이 없습니다. S – vldmrrdjcc

2

기본 스트림의 속성은 Position버퍼 상기에서는 StreamReader의 커서의 위치가 아니라, 실제의 마지막 판독 된 바이트의 총수를 의미한다. '이 Stream가 마지막에 있는지 여부를 확인하기 위해

+1

문서에서이를 명확하게 말하지는 않지만 '위치'는 실제로는 버퍼가 아니라 바이트를 참조합니다. 그게 무슨 뜻인지 모르겠다. – svick