如何用管道分隔字符串

时间:2014-11-03 15:43:05

标签: delphi delphi-xe7

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

我想将数据库中保存数据的管道分开。

我错误地使用了pos功能。但我得到了数据。

在if中,我将数据插入db。

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

5 个答案:

答案 0 :(得分:7)

您也可以使用TStringList:

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

现在您可以使用lStringList.Items [index]

访问每个字段

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

答案 1 :(得分:2)

使用ExtractStrings,您可以将| |的所有值添加到TStrings - 后代。

假设fArqTStrings后代:

ExtractStrings(['|'], [], PChar(line), fArq);

答案 2 :(得分:0)

如果您使用Delphi XE3及更高版本,则可以使用Split类助手方法。

 parts:=line.Split(['|'],TStringSplitOptions.ExcludeEmpty);

答案 3 :(得分:0)

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

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

我还包括相关函数来计算节数。

P.S。这些函数实际上是基于1写的。 P.P.S.我从另一个单元中撕下了​​这些功能,并没有检查这个单元是否完整正确。 YMMV。

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

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.

答案 4 :(得分:0)

这是我使用的功能。它支持任意长度定界符(用于拆分CRLF分隔的字符串,f.i。)和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;