Delphi xe2 读取文本文件-单行与多行

Delphi xe2 读取文本文件-单行与多行,delphi-xe2,Delphi Xe2,我正在处理一个特定的场景,在这个场景中,我必须读取文本文件,解析它,从中提取有意义的信息,使用这些信息执行SQL查询,然后生成一个响应输出文件 我有大约3000行代码。一切正常。然而,我一直在考虑一个可能会使我的项目破裂的问题 正在读取的文本文件(称之为text.txt)可能由一行或多行组成 在我的例子中,一条“线”是通过它的段名来识别的——比如ISA、BHT、HB、NM1等等。。。每个段的结尾都由一个特殊字符“~”标识 现在,如果文件由多行组成(每行对应一个段);说:- ISA~ NM1~ D

我正在处理一个特定的场景,在这个场景中,我必须读取文本文件,解析它,从中提取有意义的信息,使用这些信息执行SQL查询,然后生成一个响应输出文件

我有大约3000行代码。一切正常。然而,我一直在考虑一个可能会使我的项目破裂的问题

正在读取的文本文件(称之为text.txt)可能由一行或多行组成

在我的例子中,一条“线”是通过它的段名来识别的——比如ISA、BHT、HB、NM1等等。。。每个段的结尾都由一个特殊字符“~”标识

现在,如果文件由多行组成(每行对应一个段);说:-

ISA~

NM1~

DMG~

SE~

等等。。。。然后,我的代码基本上读取每个“行”(即每个段),一次读取一行,并使用以下命令将其存储到临时缓冲区中:-

         ReadLn(myFile,buffer);
然后根据每一行执行评估。产生所需的输出。没问题


然而问题是。。。如果文件仅由一行(由多个段组成)组成,表示为:-

ISA~NM1~DMG~SE~

然后用ReadLine命令读取整行,而不是每段,一次读取一段。这不适用于我的代码

我正在考虑创建一个if,else语句对…它基于我的Txt.Txt文件包含多少行…例如:-

如果行=1:- 然后一次提取每个片段…由特殊字符“~”分隔 执行必要的任务(3000行代码) 否则,如果行>1:- 然后一次提取每条线(对应于每条线段) 执行必要的任务(3000行代码)

现在3000行代码重复了两次,我觉得复制和粘贴所有代码两次并不优雅


如果我能得到一些关于如何解决这个问题的反馈,我将不胜感激,这样,无论是一行文件还是多行文件……当我继续评估时,我一次只使用一个段。

我将通过Win32 API
CreateFileMapping()
MapViewOfFile()
函数使用文件映射,然后按原样解析原始数据,扫描
~
字符,忽略每个段之间可能遇到的任何换行符。例如:

var
  hFile: THandle;
  hMapping: THandle;
  pView: Pointer;
  FileSize, I: DWORD;
  pSegmentStart, pSegmentEnd: PAnsiChar;
  sSegment: AnsiString;
begin
  hFile := CreateFile('Path\To\Text.txt', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if hFile = INVALID_HANDLE_VALUE then RaiseLastOSError;
  try
    FileSize := GetFileSize(hFile, nil);
    if FileSize = INVALID_FILE_SIZE then RaiseLastOSError;
    if FileSize > 0 then
    begin
      hMapping := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, FileSize, nil);
      if hMapping = 0 then RaiseLastOSError;
      try
        pView := MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, FileSize);
        if pView = nil then RaiseLastOSError;
        try
          pSegmentStart := PAnsiChar(pView);
          pSegmentEnd := pSegmentStart;
          I := 0;
          while I < FileSize do
          begin
            if pSegmentEnd^ = '~' then
            begin
              SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
              // use sSegment as needed...
              pSegmentStart := pSegmentEnd + 1;
              Inc(I);
              while (I < FileSize) and (pSegmentStart^ in [#13, #10]) do
              begin
                Inc(pSegmentStart);
                Inc(I);
              end;
              pSegmentEnd := pSegmentStart;
            end else
            begin
              Inc(pSegmentEnd);
              Inc(I);
            end;
          end;
          if pSegmentEnd > pSegmentStart then
          begin
            SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
            // use sSegment as needed...
          end;
        finally
          UnmapViewOfFile(pView);
        end;
      finally
        CloseHandle(hMapping);
      end;
    end;
  finally
    CloseHandle(hFile);
  end;
var
hFile:THandle;
hMapping:THandle;
pView:指针;
文件大小,I:DWORD;
pSegmentStart,pSegmentEnd:PAnsiChar;
片段:AnsiString;
开始
hFile:=CreateFile('Path\To\Text.txt',GENERIC\u READ,FILE\u SHARE\u READ,nil,OPEN\u EXISTING,0,0);
如果hFile=无效的句柄值,则RAISELASTERROR;
尝试
FileSize:=GetFileSize(hFile,nil);
如果FileSize=无效的文件大小,则RAISELASTERROR;
如果文件大小>0,则
开始
hMapping:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,FileSize,nil);
如果hMapping=0,则RAISELASTERROR;
尝试
pView:=MapViewOfFile(hMapping,FILE\u MAP\u READ,0,0,FileSize);
如果pView=nil,则为r;
尝试
pSegmentStart:=PAnsiChar(pView);
pSegmentEnd:=pSegmentStart;
I:=0;
而我是这么做的
开始
如果pSegmentEnd^='~'那么
开始
SetString(segment、pSegmentStart、Integer(pSegmentEnd-pSegmentStart));
//根据需要使用sSegment。。。
pSegmentStart:=pSegmentEnd+1;
公司(一);
而[#13,#10]中的(IpSegmentStart,则
开始
SetString(segment、pSegmentStart、Integer(pSegmentEnd-pSegmentStart));
//根据需要使用sSegment。。。
结束;
最后
取消pviewoffile(pView);
结束;
最后
闭柄(hMapping);
结束;
结束;
最后
闭合手柄(hFile);
结束;

我将通过Win32 API
CreateFileMapping()
MapViewOfFile()
函数使用文件映射,然后按原样解析原始数据,扫描
~
字符并忽略每个段之间可能遇到的任何换行符。例如:

var
  hFile: THandle;
  hMapping: THandle;
  pView: Pointer;
  FileSize, I: DWORD;
  pSegmentStart, pSegmentEnd: PAnsiChar;
  sSegment: AnsiString;
begin
  hFile := CreateFile('Path\To\Text.txt', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if hFile = INVALID_HANDLE_VALUE then RaiseLastOSError;
  try
    FileSize := GetFileSize(hFile, nil);
    if FileSize = INVALID_FILE_SIZE then RaiseLastOSError;
    if FileSize > 0 then
    begin
      hMapping := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, FileSize, nil);
      if hMapping = 0 then RaiseLastOSError;
      try
        pView := MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, FileSize);
        if pView = nil then RaiseLastOSError;
        try
          pSegmentStart := PAnsiChar(pView);
          pSegmentEnd := pSegmentStart;
          I := 0;
          while I < FileSize do
          begin
            if pSegmentEnd^ = '~' then
            begin
              SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
              // use sSegment as needed...
              pSegmentStart := pSegmentEnd + 1;
              Inc(I);
              while (I < FileSize) and (pSegmentStart^ in [#13, #10]) do
              begin
                Inc(pSegmentStart);
                Inc(I);
              end;
              pSegmentEnd := pSegmentStart;
            end else
            begin
              Inc(pSegmentEnd);
              Inc(I);
            end;
          end;
          if pSegmentEnd > pSegmentStart then
          begin
            SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
            // use sSegment as needed...
          end;
        finally
          UnmapViewOfFile(pView);
        end;
      finally
        CloseHandle(hMapping);
      end;
    end;
  finally
    CloseHandle(hFile);
  end;
var
hFile:THandle;
hMapping:THandle;
pView:指针;
文件大小,I:DWORD;
pSegmentStart,pSegmentEnd:PAnsiChar;
片段:AnsiString;
开始
hFile:=CreateFile('Path\To\Text.txt',GENERIC\u READ,FILE\u SHARE\u READ,nil,OPEN\u EXISTING,0,0);
如果hFile=无效的句柄值,则RAISELASTERROR;
尝试
FileSize:=GetFileSize(hFile,nil);
如果FileSize=无效的文件大小,则RAISELASTERROR;
如果文件大小>0,则
开始
hMapping:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,FileSize,nil);
如果hMapping=0,则RAISELASTERROR;
尝试
pView:=MapViewOfFile(hMapping,FILE\u MAP\u READ,0,0,FileSize);
如果pView=nil,则为r;
尝试
pSegmentStart:=PAnsiChar(pView);
pSegmentEnd:=pSegmentStart;
I:=0;
而我是这么做的
开始
如果pSegmentEnd^='~'那么
开始
SetString(segment、pSegmentStart、Integer(pSegmentEnd-pSegmentStart));
//根据需要使用sSegment。。。
pSegmentStart:=pSegmentEnd+1;
公司(一);
而[#13,#10]中的(I