(대형 파일에 사용 가능) 텍스트 파일을 빠르게 스캔하여 행 수를 집계하고 각 행의 인덱스 위치(Delphi, C#)를 반환합니다.

5436 단어 C#학습 노트
프로젝트에 따라 1200만 줄의 텍스트 파일을 스캔해야 합니다.네티즌의 지적과 테스트를 통해 C#와 델피의 차이가 결코 크지 않다는 것을 발견하였다.긴 설명 없이 열 코드 테스트:
다음은 Delphi 코드입니다.
//             
function ScanEnterFile(const FileName:string):TInt64Array;
var
  MyFile:TMemoryStream;//    
  rArray:TInt64Array;       //      
  size,curIndex:int64;//    ,     
  enterCount:int64;//    
  DoLoop:Boolean;//      
  pc: PChar;
  arrayCount:int64;//        
  addStep:integer;//                
begin
  if fileName = '' then
    Exit;
  if not FileExists(fileName) then
    Exit;
  MyFile:=TMemoryStream.Create;//   
  MyFile.LoadFromFile(fileName);//       MyFile  
  size:=MyFile.Size;
  pc:=MyFile.Memory; //          
  curIndex:=RowLeast;
  DoLoop:=true;
  enterCount:=0;
  setlength(rArray,perArray);
  arrayCount:=perArray;
  enterCount:=0;
  rArray[enterCount]:=0;
  while DoLoop do
  begin
    addStep:=0;
    if (ord(pc[curIndex])=13) then
      addStep:=2;
    if (ord(pc[curIndex])=10) then
      addStep:=1;
    //      
    if (addStep<>0) then
    begin
      Application.ProcessMessages;
      //      
      inc(enterCount);
      //          
      if (enterCount mod perArray=0) then
      begin
        arrayCount:=arrayCount+perArray;
        setlength(rArray,arrayCount);
      end;
      rArray[enterCount]:=curIndex+addStep;
      curIndex:=curIndex+addStep+RowLeast;
    end
    else
      curIndex:=curIndex+2;
    if curIndex> size then
      DoLoop:=false
    else
      DoLoop:=true;
  end;
  result:=rArray;
  freeandnil(MyFile);
end;

실행 코드:
procedure TMainForm.btn2Click(Sender: TObject);
var
  datasIndex:TInt64Array;//      
begin

  t1:=GetTickCount;
  datasIndex:=ScanEnterFile('R:\201201_dataFile.txt');
  Caption:=Caption+'::'+inttostr(GetTickCount-t1); 
end;

실행 결과: 16782ms
다음은 C# 코드입니다.
/// 
        ///       ,       ,             (1.2KW           10 )
        /// 
        ///    
        ///   
        ///       
        ///         
        ///           
        ///     
        public static IList ScanEnterFile(string fileName, out int rowCount, int rowLeast,ThreadProgress progress)
        {
            rowCount = 0;
            if (string.IsNullOrEmpty(fileName))
                return null;
            if (!System.IO.File.Exists(fileName))
                return null;
            FileStream myFile = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 8);//      
            IList rList=new List();
            int enterCount = 0;//    
            int checkValue;
            int addStep;
            myFile.Position = rowLeast;
            checkValue = myFile.ReadByte();
            while (checkValue != -1)
            {
                //Application.DoEvents();
                addStep = -1;
                //    ReadByte  ,              。
                //  ,           ,      。
                //            ,       
                if (checkValue == 13)
                    addStep = 1;
                else if (checkValue == 10)
                    addStep = 0;
                if (addStep >= 0)
                {
                    enterCount++;
                    rList.Add(myFile.Position + addStep);
                    myFile.Seek(rowLeast + addStep, SeekOrigin.Current);
                    progress(enterCount);
                }
                else myFile.Seek(2, SeekOrigin.Current);
                checkValue = myFile.ReadByte();
            }
            rowCount = enterCount + 1;
            return rList;
        }

실행 코드:
Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int rowCount;
            FileHelper.ScanEnterFile(@"R:\201201_dataFile.txt", out rowCount, 35, outputProgress);
            useTime = stopwatch.ElapsedMilliseconds;

실행 결과:
124925  ms
(많은 네티즌들의 비판과 지적을 통해 이 방법은 파일을 메모리에서 읽지 않고 한 바이트씩 읽는다. Delphi 바이트가 메모리에 들어가는 방법보다 속도가 훨씬 느리다. 이런 방법은 낡은 기계에만 적합하다. 메모리가 부족한 상황에서 현재 메모리는 이미 매우 싸다. 그래서 이 방법은 현재 이미 유행이 지났다. 다음은 네티즌의 지적을 거쳐readline 방법을 사용했다. 속도는 약 6초 정도이다.)
public static IList ScanEnterFile(string fileName, ThreadProgress progress)
        {
            if (string.IsNullOrEmpty(fileName))
                return null;
            if (!System.IO.File.Exists(fileName))
                return null;
            IList rList = new List();
            rList.Add(0);
            StreamReader sr = File.OpenText(fileName);
            string rStr = sr.ReadLine();
            while (null != rStr)
            {
                rList.Add(rList[rList.Count-1] + rStr.Length + 2);
                rStr = sr.ReadLine();
                progress(rList.Count);
            }
            sr.Close();
            return rList;
        }

테스트를 통해 이 방법은 중국어 문자 인코딩이 존재할 때 위치가 잘못되었습니다.나중에 해결 방법을 찾은 후에 다시 올라와서 갱신하세요.
테스트 결과 C# 은 배열보다 Ilist 를 더 빨리 사용합니다.
총괄: 모든 사물은 존재할 가치가 있다. 관청에서 무엇을 선택하는지는 자신의 수요에 따라 선택한다. 여기서 본인은 어느 쪽에 치우치지 않는다.어쨌든 일을 이룰 수 있다면 아무것도 중요하지 않다.
오리지널 작품은 열심히 게으름을 피우는 데서 나온 것이니, 옮겨 싣고 설명해 주십시오.
글의 출처
: http://blog.csdn.net/kfarvid
또는
http://www.cnblogs.com/kfarvid/

좋은 웹페이지 즐겨찾기