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