답변:
심각하게 뒤늦은 편집 : .NET 4.0 이상을 사용하는 경우
이 File
클래스에는 ReadLines
행을 모두 탐욕스럽게 읽지 않고 게으르게 열거 하는 새로운 메소드가 ReadAllLines
있습니다. 이제 효율성과 간결성을 모두 얻을 수 있습니다.
var lineCount = File.ReadLines(@"C:\file.txt").Count();
원래 답변
효율성에 대해 너무 신경 쓰지 않으면 간단히 다음과 같이 쓸 수 있습니다.
var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
보다 효율적인 방법을 위해 다음을 수행 할 수 있습니다.
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
while (reader.ReadLine() != null)
{
lineCount++;
}
}
편집 : 효율성에 대한 질문에 대한 답변
두 번째가 더 효율적이라고 말한 이유는 반드시 속도가 아니라 메모리 사용에 관한 것이 었습니다. 첫 번째 파일은 파일의 전체 내용을 배열로로드합니다. 즉, 파일의 크기만큼 메모리를 할당해야합니다. 두 번째는 한 번에 한 줄씩 반복하므로 한 번에 두 줄 이상의 메모리를 할당 할 필요가 없습니다. 작은 파일의 경우 그렇게 중요하지 않지만 큰 파일의 경우 문제가 될 수 있습니다 (예를 들어 32 비트 시스템에서 4GB 파일의 줄 수를 찾으려면 충분하지 않습니다) 이 큰 배열을 할당하기위한 사용자 모드 주소 공간).
속도면에서 나는 그것에 많이있을 것으로 기대하지 않을 것입니다. ReadAllLines에 내부 최적화가있을 수 있지만 다른 한편으로는 엄청난 양의 메모리를 할당해야 할 수도 있습니다. 작은 파일의 경우 ReadAllLines가 더 빠를 수 있지만 큰 파일의 경우 크게 느려질 수 있습니다. 말할 수있는 유일한 방법은 스톱워치 또는 코드 프로파일 러로 측정하는 것입니다.
ReadLines().Count()
를 추가해야합니다 using System.Linq
. 그 추가를 요구하는 것은 직관적이지 않은 것처럼 보였으므로 이것이 내가 언급 한 이유입니다. Visual Studio를 사용하는 경우이 추가가 자동으로 수행 될 수 있습니다.
쉽게 해독 할 수 있지만 기회 당 비효율적 인 코드 줄을 의미합니까?
string[] lines = System.IO.File.RealAllLines($filename);
int cnt = lines.Count();
그것은 아마도 몇 줄을 알 수있는 가장 빠른 방법 일 것입니다.
당신은 또한 할 수 있습니다 (버퍼링하는지에 따라)
#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}
다른 많은 방법이 있지만 위의 방법 중 하나가 아마도 당신과 함께 갈 것입니다.
파일을 읽고 그 자체로 시간이 오래 걸리고, 결과를 가비지 수집하는 것은 개행 문자를 세기 위해 전체 파일을 읽을 때 또 다른 문제입니다.
어느 시점에서 누군가 프레임 워크 또는 코드인지 여부에 관계없이 파일의 문자를 읽어야합니다. 이것은 파일이 크면 파일을 열고 메모리로 읽어야한다는 것을 의미합니다. 메모리가 가비지 수집되어야하기 때문에 잠재적으로 문제가 될 수 있습니다.
Nima Ara는 당신이 고려할만한 훌륭한 분석을했습니다.
다음은 한 번에 4자를 읽고 줄 바꿈 문자를 세고 다음 문자 비교를 위해 동일한 메모리 주소를 다시 재사용함에 따라 제안 된 솔루션입니다.
private const char CR = '\r';
private const char LF = '\n';
private const char NULL = (char)0;
public static long CountLinesMaybe(Stream stream)
{
Ensure.NotNull(stream, nameof(stream));
var lineCount = 0L;
var byteBuffer = new byte[1024 * 1024];
const int BytesAtTheTime = 4;
var detectedEOL = NULL;
var currentChar = NULL;
int bytesRead;
while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
var i = 0;
for (; i <= bytesRead - BytesAtTheTime; i += BytesAtTheTime)
{
currentChar = (char)byteBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 1];
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 2];
if (currentChar == detectedEOL) { lineCount++; }
currentChar = (char)byteBuffer[i + 3];
if (currentChar == detectedEOL) { lineCount++; }
}
else
{
if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
i -= BytesAtTheTime - 1;
}
}
for (; i < bytesRead; i++)
{
currentChar = (char)byteBuffer[i];
if (detectedEOL != NULL)
{
if (currentChar == detectedEOL) { lineCount++; }
}
else
{
if (currentChar == LF || currentChar == CR)
{
detectedEOL = currentChar;
lineCount++;
}
}
}
}
if (currentChar != LF && currentChar != CR && currentChar != NULL)
{
lineCount++;
}
return lineCount;
}
위에서 당신은 줄 바꿈을보기 위해 모든 문자를 읽을 필요가있을 때 기본 프레임 워크에 의해 한 번에 한 문자 씩 읽히는 것을 볼 수 있습니다.
완료된 베이 니마로 프로파일 링하면 이것이 빠르고 효율적인 방법임을 알 수 있습니다.
실행 가능한 옵션과 개인적으로 사용한 옵션은 파일의 첫 번째 줄에 자신의 헤더를 추가하는 것입니다. 내 게임의 사용자 지정 모델 형식으로이 작업을 수행했습니다. 기본적으로 내 .obj 파일을 최적화하고 필요없는 쓰레기를 제거하고 더 나은 레이아웃으로 변환 한 다음 총 선,면, 법선, 정점 및 질감 UV를 작성하는 도구가 있습니다. 첫 줄. 그런 다음이 데이터는 모델이로드 될 때 다양한 배열 버퍼에서 사용됩니다.
이 기능은 파일을 한 번만 반복하여로드하기 위해 한 번만 실행하는 것이 아니라 한 번에 한 줄을 계산하지 않고 생성 된 버퍼로 데이터를 다시 읽어야하기 때문에 유용합니다.
try {
string path = args[0];
FileStream fh = new FileStream(path, FileMode.Open, FileAccess.Read);
int i;
string s = "";
while ((i = fh.ReadByte()) != -1)
s = s + (char)i;
//its for reading number of paragraphs
int count = 0;
for (int j = 0; j < s.Length - 1; j++) {
if (s.Substring(j, 1) == "\n")
count++;
}
Console.WriteLine("The total searches were :" + count);
fh.Close();
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}