2009-09-23 5 views
2

C# 응용 프로그램에서는 한 줄씩 구분 된 7 자리 문자열을 가진 간단한 텍스트 문서를 ReadLine()에 공급하려고합니다. 내가하려고하는 것은 함수가 호출 될 때마다 다음 7 자리 문자열을 가져 오는 것입니다. 여기에 지금까지이 작업은 다음과 같습니다함수 호출의 다음 줄에 C# ReadLine()을 추가하십시오.

string invoiceNumberFunc() 
    { 
     string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt"; 
     try 
     { 
      using (StreamReader sr = new StreamReader(path)) 
      { 
       invoiceNumber = sr.ReadLine(); 

      } 

     } 
     catch (Exception exp) 
     { 
      Console.WriteLine("The process failed: {0}", exp.ToString()); 
     } 
     return invoiceNumber; 
    } 

어떻게 다음 라인에 invoiceNumberFunc()가 호출 될 때마다 발전합니까?

미리 감사드립니다.

답변

8

호출 사이에 StreamReader을 유지하고 메서드에 새 매개 변수로 전달하거나 클래스의 멤버 변수로 지정해야합니다.

void DoStuff() 
{ 
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt"; 
    using (StreamReader sr = new StreamReader(path)) 
    { 
     while (keepGoing) // Whatever logic you have 
     { 
      string invoice = InvoiceNumberFunc(sr); 
      // Use invoice 
     } 
    } 
} 

string InvoiceNumberFunc(TextReader reader) 
{ 
    string invoiceNumber; 
    try 
    { 
     invoiceNumber = reader.ReadLine(); 
    } 
    catch (Exception exp) 
    { 
     Console.WriteLine("The process failed: {0}", exp.ToString()); 
    } 
    return invoiceNumber; 
} 
1

새 StreamLister를 만드는 대신 동일한 StreamReader를 사용해야합니다. 새 파일을 생성하고 이전 파일을 삭제할 때마다 파일 시작 부분에서 바로 시작합니다.

스트림에있는 위치의 레코드를 동일한 StreamReader 참조에 전달하거나 필요할 경우 기본 스트림에서 Seek()를 사용하십시오. 이 중 첫 번째를 개인적으로 권하고 싶습니다.

1

당신이 재 작업을 할 필요가 있으므로, : 관리하기 위해 평생 쉽게 - 그것은 결코 멤버 변수로 끝나는되지 않도록

는 개인적으로 나는, 매개 변수가되고 그것의 아이디어를 선호 메서드 내에서 스트림 판독기를 만들지 않고 클래스 수준에서 스트림 판독기를 만들고 메소드에서 스트림 판독기를 사용한 다음 완료되면 판독기를 폐기하거나 닫는 것입니다. 뭔가 같은 :

이 경우
class MyClass 
{ 
    private StreamReader sr; 

    string invoiceNumberFunc() 
    { 
     if (sr == null) 
      sr = new StreamReader(path); 

     if (sr.EndOfStream) { 
      sr.Close(); 
      sr = null; 
      return string.Empty; 
     } 

     try { 
      return sr.ReadLine(); 
     } 
     catch(Exception exp) { 
      Console.WriteLine("Process failed {0}",exp.ToString()); 
      return string.Empty; 
     } 
    } 
} 

, 그것은 대신, 클래스 IDisposable은 그래서 당신은/"가까운"루틴을 "초기화"할 가능성도에서는 StreamReader가 배치됩니다 있는지 확인 할 수 있도록 좋은 생각이 될 수 있습니다 여기에서 내가 어떻게했는지 초기화 및 종료하는 것.

2

함수에서 스트림 판독기를 만들고 처리 할 수 ​​없기 때문에 사용자가 스트림을 읽을 수 없습니다. 두 가지 방법이 고려 될 것입니다 :

스트림 변수를 멤버 변수에 저장하거나 한 번에 모두 읽고 멤버 변수에 배열을 저장할 수 있습니다.

또는 당신이 그것을에 using 블록의 일부를 IEnumerable<string>에 반환 유형을 변경하고 변경하여 반복자 방법합니다

while ((invoiceNumber = sr.ReadLine()) != null) { 
    yield return invoiceNumber; 
} 

이 방법을, 당신은 당신의 invoiceNumberFuncforeach를 호출 할 수 있습니다. 각에 대한 간단한이 함수의 반환 소비 할 수

이제
IEnumerable<string> GetInvoiceNumbers() 
{ 
    string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt"; 
    using (StreamReader sr = new StreamReader(path)) 
    { 
     while (!sr.EndOfStream) 
     { 
      yield return sr.ReadLine(); 
     } 
    } 
} 

: - - :

foreach(string invoiceNumber in GetInvoiceNumbers()) 
{ 
    //Do Stuff with invoice number 
} 

또는 LINQ와 창조적

+2

파일 형식의 선을 읽는 반복자 블록은 제가 가장 좋아하는 패턴 중 하나입니다. –

1

은 무엇 당신이 찾고있는 것은 yield 명령입니다 .

1

이 일의 다른 방법은 당신이 당신의 시도에 마침내 절을 추가 확인하고 항복 수익으로 잡을 수없는 제거있는 유일한 방법 인 yield return statement

를 사용하여 반복자 블록에 함수를 변환하는 것입니다 벌거 벗은 try/catch에서 사용하십시오. 그래서 당신의 코드는 다음과 같이 될 것입니다 :

IEnumerable<String> invoiceNumberFunc() 
    { 
     string path = @"C:\Users\sam\Documents\GCProg\testReadFile.txt"; 
     try 
     { 
      using (System.IO.StreamReader sr = new System.IO.StreamReader(path)) 
      { 
       String invoiceNumber; 
       while ((invoiceNumber = sr.ReadLine()) != null) 
       { 
        yield return sr.ReadLine(); 
       } 
      } 
     } 
     finally 
     { 
     } 
    } 
+0

+1, 캐치 문제에 대해 잘 잡으십시오. – AnthonyWJones

+1

음, 드디어 전체적으로 시도해 보지 않겠습니까? 이 경우에는 아무런 효과가 없습니다. –

관련 문제