텍스트 파일 내 줄 수 결정


209

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

답변:


396

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


2
작은 참고 : String은 참조 유형이므로 배열은 행 수의 크기 x 포인터의 크기이지만 각 행을 단일 String 객체로 텍스트를 저장해야한다는 것이 맞습니다.
Mike Dimmick

16
참고 : 그렇게하려면 포함에 ReadLines().Count()를 추가해야합니다 using System.Linq. 그 추가를 요구하는 것은 직관적이지 않은 것처럼 보였으므로 이것이 내가 언급 한 이유입니다. Visual Studio를 사용하는 경우이 추가가 자동으로 수행 될 수 있습니다.
Nucleon

2
"File.ReadLines.Count ()"v / s "reader.ReadLine ()"및 "reader.ReadLine ()"두 가지 방법을 모두 약간 테스트했지만 약간의 마진으로 더 빠릅니다. "ReadAllLines"는 느슨해져 두 배의 시간이 걸리고 많은 메모리를 소비합니다). "File.ReadLines.Count ()"및 "reader.ReadLine ()"은 줄 단위로 파일을 읽고 메모리에 전체 파일을로드하지 않는 열거 자이므로 RAM에서 다시 읽습니다.
Yogee

9
예, 아무도 4GB 이상 파일을 사용하지 않습니다. 우리는 확실히 큰 로그 파일을 다루지 않습니다. 아 잠깐만
Greg Beech

2
File.ReadLines ()의 내부를 보려면 여기로 이동하십시오. System.IO.File.cs 오버로드를 드릴 다운하면 여기로 이동합니다. ReadLinesIterator.cs
Steve Kinyon

12

제일 쉬운:

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

8

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

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

5

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

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

다른 많은 방법이 있지만 위의 방법 중 하나가 아마도 당신과 함께 갈 것입니다.


3
나는이 방법이 매우 비효율적이라고 주장한다. 왜냐하면 전체 파일을 메모리와 문자열 배열로 읽어 들이기 때문입니다. ReadLine을 사용할 때 버퍼를 복사 할 필요가 없습니다. @GregBeech의 답변을 참조하십시오. 퍼레이드에 비 가서 죄송합니다.
Mike Christian

2

텍스트를 전혀 읽지 않고 빠르게 읽고 카운터를 증가시킬 수 있습니다. 루프를 사용하여 증가시킬 수 있습니다.


3
이것은 답변이 아닌 의견이어야합니다.
IamBatman

2

파일을 읽고 그 자체로 시간이 오래 걸리고, 결과를 가비지 수집하는 것은 개행 문자를 세기 위해 전체 파일을 읽을 때 또 다른 문제입니다.

어느 시점에서 누군가 프레임 워크 또는 코드인지 여부에 관계없이 파일의 문자를 읽어야합니다. 이것은 파일이 크면 파일을 열고 메모리로 읽어야한다는 것을 의미합니다. 메모리가 가비지 수집되어야하기 때문에 잠재적으로 문제가 될 수 있습니다.

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

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

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


1

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


1

실행 가능한 옵션과 개인적으로 사용한 옵션은 파일의 첫 번째 줄에 자신의 헤더를 추가하는 것입니다. 내 게임의 사용자 지정 모델 형식으로이 작업을 수행했습니다. 기본적으로 내 .obj 파일을 최적화하고 필요없는 쓰레기를 제거하고 더 나은 레이아웃으로 변환 한 다음 총 선,면, 법선, 정점 및 질감 UV를 작성하는 도구가 있습니다. 첫 줄. 그런 다음이 데이터는 모델이로드 될 때 다양한 배열 버퍼에서 사용됩니다.

이 기능은 파일을 한 번만 반복하여로드하기 위해 한 번만 실행하는 것이 아니라 한 번에 한 줄을 계산하지 않고 생성 된 버퍼로 데이터를 다시 읽어야하기 때문에 유용합니다.


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

5
-1 : 느리고 메모리를 많이 사용하며 GC에 어려움을 겪습니다!
ya23

-2

" wc .exe"실행 파일 ( UnixUtils 와 함께 제공되며 설치가 필요하지 않음)을 외부 프로세스로 실행할 수 있습니다. 유닉스 대 맥 대 윈도우와 같은 다른 라인 카운트 방법을 지원합니다.


1
이것이 유용 할만큼 빠를 방법은 없습니다. 실행 파일을 호출하는 오버 헤드는 단일 증분 루프의 두 배 (명백한 과장)가 될 것입니다.
Krythic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.