나는 200.000 줄 이상의 큰 텍스트 파일을 가지고 있으며 몇 줄을 읽어야합니다. 예 : 줄 10.000 ~ 20.000.C++의 큰 텍스트 파일에서 부분 데이터를 읽는 방법
중요 : 성능 문제로 인해 논문 줄을 추출하려면 전체 파일을 열고 검색하고 싶지 않습니다.
이것이 가능합니까?
나는 200.000 줄 이상의 큰 텍스트 파일을 가지고 있으며 몇 줄을 읽어야합니다. 예 : 줄 10.000 ~ 20.000.C++의 큰 텍스트 파일에서 부분 데이터를 읽는 방법
중요 : 성능 문제로 인해 논문 줄을 추출하려면 전체 파일을 열고 검색하고 싶지 않습니다.
이것이 가능합니까?
모든 줄이 같은 길이라는 것을 알지 못하는 한, 파일을 검색하여 줄 바꿈을 계산해야합니다 (이 경우 오프셋 = line_number * line_size_in_bytes를 찾을 수 있습니다. 여기서 line_number는 0과 line_size_in_bytes가 포함됩니다). 줄의 모든 문자).
줄이 가변적/알 수없는 길이이면 한 번 읽는 동안 각 줄의 시작 오프셋을 인덱싱하여 후속 읽기가 주어진 줄의 시작을 찾을 수 있도록 할 수 있습니다.
줄이 고정 길이이면 특정 바이트 위치를 찾고 원하는 줄만로드 할 수 있습니다. 행이 가변 길이 인 경우 찾고있는 행을 찾는 유일한 f}은 파일을 구문 분석하고 행 끝 마커의 수를 계산하는 것입니다. 파일이 자주 변경되지 않으면이 구문 분석을 한 번 수행 한 다음 향후 액세스 속도를 높이기 위해 각 행의 바이트 위치 인덱스를 유지함으로써 충분한 성능을 얻을 수 있습니다 (아마도 인덱스를 디스크에 기록하여 프로그램이 실행될 때마다 완료됩니다.)
주의 사항 : 일부 파일 형식에는 시작 부분에 인덱스가 있거나 끝 부분에 가끔 있습니다. 그런 다음 색인을 읽고이를 사용하여 필요한 데이터의 시작 위치를 계산합니다. 예, 바이너리 형식에서 더 쉽고 일반적입니다. 그러나 텍스트 형식으로 처리 된 것을 보았습니다. – dmckee
+1 대답은 @dmckee : 초기 색인은 실제 문제가 아닌 것 같습니다. 결국에는 끝까지 탐색 할 수 있으며 인덱스 크기를 알고있을 수 있으므로 큰 문제는 아닌 것 같습니다. – neuro
@neuro : 끝에있는 인덱스의 마지막 요소는 인덱스 시작 부분의 고정 크기 오프셋이어야합니다. 끝까지 추구하고, 알려진 양만큼 백업하고, 인덱스 오프셋을 읽고, 인덱스로 이동하여 거기에서부터 진행하십시오. 당연하지, 그렇지? :) – dmckee
이 줄이 모두 같은 길이이면 주어진 줄의 오프셋을 계산하고 그 줄만 읽을 수 있습니다.
줄의 길이가 다른 경우 줄 수를 계산하려면 전체 파일을 읽어야합니다. 줄 종료 문자는 파일의 임의의 바이트입니다.
선이 고정 길이이면 오프셋 만 계산하면 문제가 없습니다.
그렇지 않은 경우 (예 : 일반 CSV 파일) 색인을 작성하거나 필요한 줄을 읽으려면 파일을 거쳐야합니다. 파일을 좀 더 빨리 읽으려면 메모리 매핑 된 파일을 사용하는 것이 좋습니다 (Boost iostreams의 일부인 구현 : http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html 참조).
다른 언급했듯이 너비가 고정 된 선이 없으면 색인을 작성하지 않고는 불가능합니다. 그러나 파일의 형식을 제어하는 경우 라인 자체를 저장하는 경우 시작 행을 찾을 때 O (크기) 성능 대신 ~ O (로그 (크기))를 얻을 수 있습니다 각 라인, 즉 파일의 내용이 같은 것을 찾아 보게하기 : 파일의이 형식
1: val1, val2, val3
2: val4
3: val5, val6
4: val7, val8, val9, val10
를 신속 이진 검색하여 필요한 라인을 찾을 수 있습니다 : 파일의 중앙으로 추구로 시작합니다. 다음 줄 바꿈까지 읽으십시오. 그런 다음 줄을 읽고 번호를 파싱합니다. 숫자가 목표보다 크면 파일의 첫 번째 절반에서 알고리즘을 반복해야하며 목표 라인 번호보다 작 으면 파일의 두 번째 절반에서이를 반복해야합니다.
코너 케이스에주의해야합니다 (예 : 범위의 "시작"과 범위의 끝은 같은 라인에 있습니다). 그러나 나에게있어이 접근법은 과거에 날짜가있는 로그 파일을 구문 분석하기위한 과거 (그리고 특정 타임 스탬프 사이에있는 행을 찾아야했습니다).
물론 이것은 여전히 명시 적으로 작성된 인덱스 또는 고정 크기 레코드의 성능을 능가하지는 않습니다.
Fortran에서는 데이터 카운터 (2 백만 라인)에서 파일을 읽어야했습니다. 그래서 나는 그것이 가능하다고 확신합니다. – dassouki