3

我有一行描述如下:'|0200|4|SALGADOS|||KG|00|19051000||||17|'

我想分隔管道在数据库中保存数据的位置。

我错误地使用了 pos 函数。但我正在获取数据。

在 if then 我会将数据插入到数据库中。

ReadLn(txt, line);
if True then
  if (Pos('|0200|', line)) = 1 then
  begin
    fArq.Add(line);
  end;
  if (pos('|0000|', line)) = 1 then
  begin
    fArq.Add(line);
  end;
  if (pos('|0005|', line)) = 1 then
  begin
    fArq.Add(line);
  end;
  if (pos('|C460|', line)) = 1 then
  begin
    fArq.Add(line);
    flagCF := True;
  end
  else
  begin
    if flagCF = True then
      if (pos('|C490|', line)) = 0 then
        fArq.Add(line)
      else
        flagCF := False;
  end
4

5 回答 5

7

您还可以使用 TStringList:

lStringList := TStringList.Create;
lStringList.delimiter := '|';
lStringList.DelimitedText := '|0200|4|SALGADOS|||KG|00|19051000||||17|';

现在您可以使用 lStringList.Items[ index ] 访问每个字段


注意(来自注释):如果字符串中包含空格字符,请设置StrictDelimiter为 true 以避免将它们视为分隔符。

于 2014-11-03T16:15:52.627 回答
2

使用ExtractStrings,您可以将 | 之间的所有值添加到TStrings-descendant。

假设fArq是一个TStrings后代:

ExtractStrings(['|'], [], PChar(line), fArq);
于 2014-11-03T15:59:37.117 回答
0

我有以下功能,我已经使用了很长一段时间了。

这里有两种变体,第一种是一次性使用类型的函数,另一种是当您想要有效地处理从第一个元素到最后一个元素的整个输入字符串时。

我还包括了相关的函数来计算部分的数量。

PS这些函数实际上是基于1的,如所写。PPS 我从另一个单元中提取了功能,并没有检查这个单元的完全正确性。YMMV。

非 POS 方法被认为是一次性功能。IE。您只是在给定的输入字符串中寻找单个值。

POS 方法采用两个加法整数变量来存储内部索引位置以供以后使用。第一次调用时,变量的初始值应设置为 -1。之后,您应该只将值提供给上一个调用返回的调用的下一次迭代。

例如。

非 POS 使用:

const
  Str1 = '|0200|4|SALGADOS|||KG|00|19051000||||17|';

.
.
.

begin
  showmessage( ParseSection(Str1, 1, '|') );  //returns 0200
  showmessage( ParseSection(Str1, 4, '|') );  //returns '' (empty string)


  //this will show every element in the string once
  Idx1 := -1;
  Idx2 := -1;
  for loop := 1 to CountSections(Str1, '|') do
    showmessage( ParseSectionPos(Str1, loop, '|', Idx1, Idx2) );  
  //Idx1 and Idx2 are self referenced variables and don't need outside intervention
  //These are necessary to obtain the best possible speed
end;

该方法的其他变体允许用户定义引用值和引用字符。

unit rmControls.Strings.Sections;

interface

uses System.Classes, System.SysUtils;

function CountSections(const ParseLine: string; const ParseSep: char): integer; overload;
function CountSections(const ParseLine: string; const ParseSep: char; const QuotedStrChar: char): integer; overload;

function ParseSection(const ParseLine: string; ParseNum: integer; const ParseSep: char): string; overload;
function ParseSection(const ParseLine: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char): string; overload;

function ParseSectionPos(const ParseLine: string; ParseNum: integer; const ParseSep: char; var FromIDX, FromPOS: integer): string; overload;
function ParseSectionPos(const ParseLine: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char; var FromIDX, FromPOS: integer): string; overload;

function UpdateSection(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char):string; overload;
function UpdateSection(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char):string; overload;

function UpdateSectionPos(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; var FromIDX, FromPOS: integer):string; overload;
function UpdateSectionPos(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char; var FromIDX, FromPOS: integer):string; overload;

implementation

uses System.Math, System.Masks, System.Character, System.Variants;

function CountSections(const ParseLine: string; const ParseSep: char; const QuotedStrChar: char): integer; overload;
var
  wEnd: PChar;
  Loop: integer;
  wInQuote: boolean;
begin
  wInQuote := false;
  wEnd := PChar(ParseLine);
  result := 0;

  for Loop := 1 to Length(ParseLine) do
  begin
    if (wEnd^ = QuotedStrChar) then
      wInQuote := not wInQuote;

    if not wInQuote and (wEnd^ = ParseSep) then
      inc(result);
    inc(wEnd);
  end;
  if Length(ParseLine) <> 0 then
    inc(result);
end; { CountSections }

function CountSections(const ParseLine: string; const ParseSep: char): integer; overload;
var
  wEnd: PChar;
  Loop: integer;
begin
  wEnd := PChar(ParseLine);
  result := 0;
  for Loop := 1 to Length(ParseLine) do
  begin
    if (wEnd^ = ParseSep) then
      inc(result);
    inc(wEnd);
  end;
  if Length(ParseLine) <> 0 then
    inc(result);
end; { CountSections }

function ParseSection(const ParseLine: string; ParseNum: integer; const ParseSep: char): string; overload;
var
  w1, w2: integer;
begin
  w1 := -1;
  w2 := -1;
  result := ParseSectionPos(ParseLine, ParseNum, ParseSep, w1, w2);
end; { ParseSection }

function ParseSection(const ParseLine: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char): string;  overload;
var
  w1, w2: integer;
begin
  w1 := -1;
  w2 := -1;
  result := ParseSectionPos(ParseLine, ParseNum, ParseSep, QuotedStrChar, w1, w2);
end; { ParseSection }

function ParseSectionPos(const ParseLine: string; ParseNum: integer; const ParseSep: char; var FromIDX, FromPOS: integer): string;
var
  wStart, wEnd: PChar;
  wIndex, Loop: integer;
  wLoopIDX: integer;
begin
  wIndex := 1;
  wLoopIDX := 1;
  wEnd := PChar(ParseLine);
  if (FromIDX > -1) and (FromIDX < Length(ParseLine)) then
  begin
    inc(wEnd, FromIDX);
    wIndex := FromPOS;
    wLoopIDX := FromIDX;
  end;
  wStart := wEnd;

  for Loop := wLoopIDX to Length(ParseLine) do
  begin
    if (wEnd^ = ParseSep) then
    begin
      if wIndex = ParseNum then
        break
      else
      begin
        inc(wIndex);
        inc(wEnd);
        wStart := wEnd;
      end;
    end
    else
      inc(wEnd);
  end;

  if wIndex = ParseNum then
  begin
    SetString(result, wStart, wEnd - wStart);
    if result = #0 then
      result := '';
    FromIDX := wEnd - PChar(ParseLine);
    FromPOS := ParseNum;
  end
  else
    result := '';
end;

function ParseSectionPos(const ParseLine: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char; var FromIDX, FromPOS: integer): string;
var
  wStart, wEnd: PChar;
  wIndex, Loop: integer;
  wInQuote: boolean;
  wLoopIDX: integer;
begin
  wInQuote := false;
  wIndex := 1;
  wLoopIDX := 1;

  wEnd := PChar(ParseLine);
  if (FromIDX > -1) and (FromIDX < Length(ParseLine)) then
  begin
    inc(wEnd, FromIDX);
    wIndex := FromPOS;
    wLoopIDX := FromIDX;
  end;
  wStart := wEnd;

  for Loop := wLoopIDX to Length(ParseLine) do
  begin
    if (wEnd^ = QuotedStrChar) then
      wInQuote := not wInQuote;

    if not wInQuote and (wEnd^ = ParseSep) then
    begin
      if wIndex = ParseNum then
        break
      else
      begin
        inc(wIndex);
        inc(wEnd);
        wStart := wEnd;
      end;
    end
    else
      inc(wEnd);
  end;

  if wIndex = ParseNum then
  begin
    SetString(result, wStart, wEnd - wStart);
    if (Length(result) > 0) and (result[1] = QuotedStrChar) then
      result := AnsiDequotedStr(result, QuotedStrChar);
    if result = #0 then
      result := '';
    FromIDX := wEnd - PChar(ParseLine);
    FromPOS := ParseNum;
  end
  else
    result := '';
end;

function UpdateSection(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char): string; overload;
var
  w1, w2: integer;
begin
  w1 := -1;
  w2 := -1;
  result := UpdateSectionPos(ParseLine, UpdateText, ParseNum, ParseSep, w1, w2);
end;

function UpdateSection(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char): string; overload;
var
  w1, w2: integer;
begin
  w1 := -1;
  w2 := -1;
  result := UpdateSectionPos(ParseLine, UpdateText, ParseNum, ParseSep, QuotedStrChar, w1, w2);
end;

function UpdateSectionPos(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; var FromIDX, FromPOS: integer):string; overload;
var
  wStart, wEnd: PChar;
  wIndex, Loop: integer;
  wLoopIDX: integer;
begin
  wIndex := 1;
  wLoopIDX := 1;
  wEnd := PChar(ParseLine);
  if (FromIDX > -1) and (FromIDX < Length(ParseLine)) then
  begin
    inc(wEnd, FromIDX);
    wIndex := FromPOS;
    wLoopIDX := FromIDX;
  end;
  wStart := wEnd;

  for Loop := wLoopIDX to Length(ParseLine) do
  begin
    if (wEnd^ = ParseSep) then
    begin
      if wIndex = ParseNum then
        break
      else
      begin
        inc(wIndex);
        inc(wEnd);
        wStart := wEnd;
      end;
    end
    else
      inc(wEnd);
  end;

  if wIndex = ParseNum then
  begin
    SetString(result, PChar(ParseLine), wStart - pChar(ParseLine));
    if result = #0 then
      result := '';
    result := result + updateText + pchar(wEnd);
    FromIDX := wEnd - PChar(ParseLine);
    FromPOS := ParseNum;
  end
  else
    raise Exception.Create('Index not found');
end;

function UpdateSectionPos(const ParseLine, UpdateText: string; ParseNum: integer; const ParseSep: char; const QuotedStrChar: char; var FromIDX, FromPOS: integer):string; overload;
var
  wStart, wEnd: PChar;
  wIndex, Loop: integer;
  wInQuote: boolean;
  wLoopIDX: integer;
begin
  wInQuote := false;
  wIndex := 1;
  wLoopIDX := 1;

  wEnd := PChar(ParseLine);
  if (FromIDX > -1) and (FromIDX < Length(ParseLine)) then
  begin
    inc(wEnd, FromIDX);
    wIndex := FromPOS;
    wLoopIDX := FromIDX;
  end;
  wStart := wEnd;

  for Loop := wLoopIDX to Length(ParseLine) do
  begin
    if (wEnd^ = QuotedStrChar) then
      wInQuote := not wInQuote;

    if not wInQuote and (wEnd^ = ParseSep) then
    begin
      if wIndex = ParseNum then
        break
      else
      begin
        inc(wIndex);
        inc(wEnd);
        wStart := wEnd;
      end;
    end
    else
      inc(wEnd);
  end;

  if wIndex = ParseNum then
  begin
    SetString(result, PChar(ParseLine), wStart - pChar(ParseLine));
    if result = #0 then
      result := '';
    result := result + AnsiQuotedStr(updateText, QuotedStrChar) + pchar(wEnd);
    FromIDX := wEnd - PChar(ParseLine);
    FromPOS := ParseNum;
  end
  else
    raise Exception.Create('Index not found');
end;

end.
于 2014-11-03T19:15:56.937 回答
0

如果您使用 Delphi XE3 及更高版本,则可以使用Split Class Helper Method。

 parts:=line.Split(['|'],TStringSplitOptions.ExcludeEmpty);
于 2014-11-03T19:07:42.840 回答
0

这是我使用的功能。它支持任意长度的定界符(用于分割 CRLF 分隔的字符串 fi)和AllowEmpty决定是否将空元素省略或返回的参数。

function Split(const Str: string; Delim: string; AllowEmpty: Boolean): TStringDynArray;
var CurrDelim, NextDelim, CurrIdx: Integer;
begin
  if Str = '' then begin SetLength(Result, 0); Exit; end;
  CurrDelim := 1; CurrIdx := 0; SetLength(Result, 16);
  repeat
    if CurrIdx = Length(Result) then
      SetLength(Result, CurrIdx + 16);                

    NextDelim := PosEx(Delim, Str, CurrDelim);        
    if NextDelim = 0 then NextDelim := Length(Str)+1; // the end of the string
    Result[CurrIdx] := Copy(Str, CurrDelim, NextDelim - CurrDelim);
    CurrDelim := NextDelim + Length(Delim);

    if (Result[CurrIdx] <> '') or AllowEmpty
      then Inc(CurrIdx)
      else Continue;
  until CurrDelim > Length(Str);
  SetLength(Result, CurrIdx);                      // cut the array to actual length
end;
于 2014-11-05T13:16:19.643 回答