텍스트 파일을 한 줄씩 읽고 싶습니다. .NET C # 범위 내에서 가능한 한 효율적으로하고 있는지 알고 싶었습니다.
이것이 지금까지 시도한 것입니다.
var filestream = new System.IO.FileStream(textFilePath,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.ReadWrite);
var file = new System.IO.StreamReader(filestream, System.Text.Encoding.UTF8, true, 128);
while ((lineOfText = file.ReadLine()) != null)
{
//Do something with the lineOfText
}
답변
파일을 한 줄씩 읽는 가장 빠른 방법을 찾으려면 벤치마킹을 수행해야합니다. 컴퓨터에서 몇 가지 작은 테스트를 수행했지만 결과가 환경에 적용되는 것을 기대할 수 없습니다.
StreamReader.ReadLine 사용
이것은 기본적으로 당신의 방법입니다. 어떤 이유로 버퍼 크기를 가능한 가장 작은 값 (128)으로 설정했습니다. 이를 늘리면 일반적으로 성능이 향상됩니다. 기본 크기는 1,024이고 다른 좋은 선택은 512 (Windows의 섹터 크기) 또는 4,096 (NTFS의 클러스터 크기)입니다. 최적의 버퍼 크기를 결정하려면 벤치 마크를 실행해야합니다. 더 큰 버퍼는 더 빠르지는 않지만 적어도 작은 버퍼보다 느리지 않습니다.
const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(fileName))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize)) {
String line;
while ((line = streamReader.ReadLine()) != null)
// Process line
}
FileStream
생성자를 지정할 수 있습니다 FileOptions을 . 예를 들어, 큰 파일을 처음부터 끝까지 순차적으로 읽는 경우 이점이있을 수 있습니다 FileOptions.SequentialScan
. 다시 한 번 벤치마킹이 최선의 방법입니다.
File.ReadLines 사용
이것은 StreamReader
고정 버퍼 크기 1,024를 사용하여 구현된다는 점을 제외하고는 자체 솔루션과 매우 유사합니다 . 내 컴퓨터에서는 버퍼 크기가 128 인 코드와 비교하여 약간 더 나은 성능을 제공합니다. 그러나 더 큰 버퍼 크기를 사용하면 동일한 성능 향상을 얻을 수 있습니다. 이 방법은 반복자 블록을 사용하여 구현되며 모든 라인에 메모리를 사용하지는 않습니다.
var lines = File.ReadLines(fileName);
foreach (var line in lines)
// Process line
File.ReadAllLines 사용
이 방법은 반환 된 행 배열을 만드는 데 사용되는 문자열 목록을 늘려 메모리 요구 사항이 더 높다는 점을 제외하면 이전 방법과 매우 유사합니다. 그러나 임의로 리턴 하여 회선에 액세스 할 수 는 String[]
없습니다 IEnumerable<String>
.
var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
var line = lines[i];
// Process line
}
String.Split 사용
이 방법은 아마도 String.Split
구현 방법으로 인해 적어도 큰 파일 (511KB 파일에서 테스트 됨)에서 상당히 느립니다 . 또한 솔루션에 비해 필요한 메모리를 늘리는 모든 라인에 배열을 할당합니다.
using (var streamReader = File.OpenText(fileName)) {
var lines = streamReader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
// Process line
}
File.ReadLines
깨끗하고 효율적이기 때문에 사용 하는 것이 좋습니다. 특별한 공유 옵션이 필요한 경우 (예 FileShare.ReadWrite
🙂 자체 코드를 사용할 수 있지만 버퍼 크기를 늘려야합니다.
답변
.NET 4를 사용 File.ReadLines
하는 경우 간단하게 사용 하십시오. 나는 그것이 또한 사용 하고 큰 버퍼 (128은 매우 작은 것)를 제외하고는 당신과 거의 동일 하다고 생각합니다 FileOptions.SequentialScan
.
답변
File.ReadAllLines()
파일을 읽는 가장 간단한 방법 중 하나 이지만 가장 느린 방법 중 하나입니다.
이 벤치 마크에 따르면 많은 일을하지 않고 파일에서 행 을 읽으려면 파일을 읽는 가장 빠른 방법은 다음과 같은 오래된 방법입니다.
using (StreamReader sr = File.OpenText(fileName))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
//do minimal amount of work here
}
}
그러나 각 줄을 많이 사용해야하는 경우이 기사에서는 가장 좋은 방법은 다음과 같다는 결론을 내립니다 (그리고 읽을 줄 수를 알고 있으면 string []을 미리 할당하는 것이 더 빠릅니다).
AllLines = new string[MAX]; //only allocate memory here
using (StreamReader sr = File.OpenText(fileName))
{
int x = 0;
while (!sr.EndOfStream)
{
AllLines[x] = sr.ReadLine();
x += 1;
}
} //Finished. Close the file
//Now parallel process each line in the file
Parallel.For(0, AllLines.Length, x =>
{
DoYourStuff(AllLines[x]); //do your work here
});
답변
다음 코드를 사용하십시오.
foreach (string line in File.ReadAllLines(fileName))
이는 읽기 성능면에서 큰 차이였습니다.
메모리 소비 비용이 들지만 그만한 가치가 있습니다!
답변
스택 오버플로 질문에서 이것에 대해 좋은 주제가 있습니다. ‘수율 반환’이 “구식”반환보다 느립니까? .
그것은 말한다 :
ReadAllLines는 모든 행을 메모리에로드하고 문자열 []을 반환합니다. 파일이 작 으면 좋습니다. 파일이 메모리에 맞는 것보다 큰 경우 메모리가 부족합니다.
반면에 ReadLine은 한 번에 한 줄씩 반환하기 위해 yield return을 사용합니다. 그것으로, 당신은 어떤 크기의 파일을 읽을 수 있습니다. 전체 파일을 메모리에로드하지 않습니다.
“foo”라는 단어가 포함 된 첫 번째 줄을 찾은 다음 종료한다고 가정합니다. ReadAllLines를 사용하면 첫 번째 줄에 “foo”가 발생하더라도 전체 파일을 메모리로 읽어야합니다. ReadLines를 사용하면 한 줄만 읽습니다. 어느 쪽이 더 빠를까요?
답변
파일 크기가 크지 않으면 전체 파일을 읽고 나중에 분할하는 것이 더 빠릅니다.
var filestreams = sr.ReadToEnd().Split(Environment.NewLine,
StringSplitOptions.RemoveEmptyEntries);
답변
메모리가 충분하면 전체 파일을 메모리 스트림 으로 읽은 다음 스트림 리더를 열어 줄을 읽음 으로써 성능이 약간 향상되었습니다 . 어쨌든 전체 파일을 실제로 읽을 계획이라면 몇 가지 개선이 이루어질 수 있습니다.