[C#] 텍스트 파일 내 줄 수 결정

텍스트 파일 내에서 줄 수를 프로그래밍 방식으로 쉽게 결정할 수 있습니까?



답변

심각하게 뒤늦은 편집 : .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가 더 빠를 수 있지만 큰 파일의 경우 크게 느려질 수 있습니다. 말할 수있는 유일한 방법은 스톱워치 또는 코드 프로파일 러로 측정하는 것입니다.


답변

제일 쉬운:

int lines = File.ReadAllLines("myfile").Length;


답변

메모리를 적게 사용하지만 시간이 더 오래 걸립니다

int count = 0;
string line;
TextReader reader = new StreamReader("file.txt");
while ((line = reader.ReadLine()) != null)
{
  count++;
}
reader.Close();


답변

쉽게 해독 할 수 있지만 기회 당 비효율적 인 코드 줄을 의미합니까?

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;
}

위에서 당신은 줄 바꿈을보기 위해 모든 문자를 읽을 필요가있을 때 기본 프레임 워크에 의해 한 번에 한 문자 씩 읽히는 것을 볼 수 있습니다.

완료된 베이 니마로 프로파일 링하면 이것이 빠르고 효율적인 방법임을 알 수 있습니다.


답변

캐리지 리턴 / 라인 피드를 계산합니다. 나는 유니 코드를 믿는데 여전히 각각 0x000D와 0x000A입니다. 그렇게하면 원하는만큼 효율적이거나 비효율적 일 수 있고 두 캐릭터를 다룰 것인지 아닌지를 결정할 수 있습니다