Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2016年12月24日] [更新 2018年05月21日] Delphi サンプルプログラム集
   
958_デリミタによる文字列の分割
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
958_SplitDelimiter.zip [6,583 KB] 2018年05月21日版 (EXE 同梱)







任意のデリミタによる文字列の分割


文字列の中の特定の文字を区切り文字 (デリミタ) として,複数の文字列に分解,分割する際の参考用のサンプルプログラムです.
後半のサンプルは複数のデリミタ文字 (区切り文字) で文字列を分割する例ですが,当然,カンマ等,1 つだけの時にも使用できます.

Windows 2000 以降,文字列操作関係の API 関数も充実してきました.Delphi も文字列操作関係の関数類が追加されてきました.Halbow 資料館にある文字列の操作関係のサンプルも説明を分ける必要がなくなってきました.






01_任意のデリミタによる文字列の分離・分割 - TStrings.Delimiter


Delphi 2006 以降では,TStrings に StrictDelimiter というプロパティ等が追加されています.この値を True にして,デリミタの文字を Delimiter プロパティで設定したあと,DelimitedText で操作できます.ネット上の掲示板等でよく質問がある「半角のスペース文字でもデータが区切られてしまう」という現象は発生しません.

次のコードは,TStringList に,あるデリミタで区切られた文字列が格納されている場合,そのデリミタをタブ文字にして,別の TStringList に格納します.その別の TStringList に格納した文字列を TStringGrid のセルに,セル単位でセットします.

後述の例のように,デリミタで区切られた文字列は,行単位あるいは,列単位でも TStringGrid にセットできます.また,TStringGird から TStringList 等へもエクスポートできます.



図1
読み込むタブ区切りテキストの内容
図2
実行結果


リスト1
TStringGrid1 の指定の行と列の範囲に,タブ区切り形式のデータをセットする例
別の TStringList (LColList) の各行に,タブ区切りの文字列をセットする
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  タブ区切りテキストファイルから文字列の読み込みの例
//  タブで区切られた文字列を取得する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LFileName : String;
  LStrList  : TStringList;
  LColList  : TStringList;
  LStartCol : Integer;
  LStartRow : Integer;
  i         : Integer;
  j         : Integer;
begin
  LFileName := ExtractFilePath(Application.ExeName) + 'ABCTAB.txt';

  LStrList := TStringList.Create;
  LColList := TStringList.Create;
  try
    //データの読み込み
    LStrList.LoadFromFile(LFileName);

    LStartCol := 2;
    LStartRow := 3;
    //TStringGridの行数を設定
    StringGrid1.RowCount := LStrList.Count + LStartRow;

    //セル単位でデータ代入
    for i := 0 to LStrList.Count - 1 do begin
      //デリミタの設定
      LColList.Delimiter       := Chr(VK_TAB);
      LColList.StrictDelimiter := True;
      LColList.DelimitedText   := LStrList[i];

      //最初だけTStringGridの列数の設定をする
      if i = 0 then begin
        StringGrid1.ColCount := LColList.Count + LStartCol;
      end;

      for j := 0 to LColList.Count - 1 do begin
        //デリミタで区切られたj番目のデータをLColListから取り出す
        StringGrid1.Cells[j + LStartCol, i + LStartRow] := LColList[j];
      end;
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

end.


カンマ区切りテキストの場合は,次のように Delimiter プロパティの値を , にします.
このコードは完全にカンマで区切り文字列を取得します.例えば "東,京,都" というテキストは,カンマを含む 東,京,都 という 1 つの文字列になります." (タプルクォーテーション) は含まれません.これが CSV テキストの仕様です.CSV テキストでは,カンマを含む文字列はダブルクォーテーションで括ることになっています.
ダブルクォーテーション内を 1 つの文字列として扱うには,Delimiter プロパティを使用します.ダブルクォーテーションも文字として扱いたい場合は,次項のサンプルで使用している SplitString 関数が利用できます.



リスト2
カンマ区切りのテキストファイルを処理する場合は,Delimiter の値を , にする
      //デリミタの設定
      LColList.Delimiter       := ',';
      LColList.StrictDelimiter := True;
      LColList.DelimitedText   := LStrList[i];






02_任意のデリミタによる文字列の分離・分割 - SplitString 関数


任意の文字で文字列を分割したり,複数の文字で分割するには,SplitString という関数も使用できます.また,ヌル終端文字列 (PChar 型) 用には ExtractStrings という関数があります.

本サンプルでは,TStreamReader でテキストファイルを行単位で読み出して文字列に代入します.その文字列を SplitString 関数を使用して,デリミタで区切られた各々の文字列を TStringDynArray 配列に格納します.

SplitString 関数は,ダブルクォーテーションも文字として認識します.例えば "東,京,都" というテキストは,
      "東
      京
      都"
という 3 つの文字列になります.
ダブルクォーテーションも文字として扱いたい場合は,SplitString 関数が便利です.




図3
読み込む CSV ファイルの内容

図4
実行結果

リスト3
任意のデリミタによる文字列の分離・分割 - SplitString 関数を使用する例
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  StrUtils,
  Types;

{$R *.dfm}

//=============================================================================
//  TStreamReaderを使用して,テキストファイルから行単位で文字列を読み出す
//  対象のファイルはカンマ区切りのテキスト(CSV)
//  カンマで区切られた各々の文字列を取得する例
//
//  TStreamReaderの使用にはusesにStrUtilsが必要
//  TStringDynArrayの使用にはusesにTypesが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LFileName      : String;
  LStreamReader  : TStreamReader;
  LLineText      : String;
  LLineTextArray : TStringDynArray;
begin
  //TStreamReaderの生成
  LFileName     := ExtractFilePath(Application.ExeName) + 'ABC.csv';
  LStreamReader := TStreamReader.Create(LFileName, TEncoding.Default);

  try
    Memo1.Lines.Clear;
    Memo1.Lines.BeginUpdate;

    while LStreamReader.EndOfStream = False do begin
      LLineText := LStreamReader.ReadLine;

      //文字列をTStringDynArray配列に格納する
      LLineTextArray := SplitString(LLineText, ',');
      for LLineText in LLineTextArray do begin
        Memo1.Lines.Add(LLineText);
      end;
      Memo1.Lines.Add(sLineBreak);
    end;
  finally
    LStreamReader.Close;
    FreeAndNil(LStreamReader);
  end;

  Memo1.Lines.EndUpdate;
end;

end.


タブ区切りのテキストの場合は,例えば以下のようにします.


      //文字列をTStringDynArray配列に格納する
      LLineTextArray := SplitString(LLineText, Chr(VK_TAB));




03_CSV やタブ区切り文字列を行単位で TStringGrid のセルへ代入


TStringList の各 Item にデリミタ付きで文字列が格納されている場合,TStringGrid 等では,行単位あるいは列単位で値をセットすることができます.
逆に,TStringGrid の行または列単位で,TStringList 等へエクスポートすることもできます.



図5
読み込む CSV ファイルの内容

図6
実行結果

リスト4
カンマで区切り文字列を,StringGrid のセルへ,行単位でデータをセット
TStringList の各行にカンマ区切りの文字列が格納されている場合
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  CSVファイルから文字列の読み込みの例
//  カンマ区切りの文字列をTStringGridのセルに行単位でセット
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LFileName : String;
  LStrList  : TStringList;
  i         : Integer;
begin
  LFileName := ExtractFilePath(Application.ExeName) + 'ABC.csv';

  LStrList := TStringList.Create;
  try
    //データの読み込み
    LStrList.LoadFromFile(LFileName);

    //TStringGridの行数と列数を設定
    StringGrid1.RowCount := LStrList.Count + StringGrid1.FixedRows;
    StringGrid1.ColCount := 5;

    //行単位でTStringListからデータを取得してTStringGridのセルにセット
    //左端の列を空白にするために,先頭にカンマを挿入
    for i := 0 to LStrList.Count -1 do begin
      LStrList[i] := ',' + LStrList[i];
      StringGrid1.Rows[i + 1].Delimiter       := ',';
      StringGrid1.Rows[i + 1].StrictDelimiter := True;
      StringGrid1.Rows[i + 1].DelimitedText   := LStrList[i];
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

end.




04_CSV 文字列を TStrings 型変数に代入 - TListBox.Items の例


これまでのサンプルで示したように,デリミタで区切られた文字列は,TStrings 型の変数に分割して代入できます.
下図は,最も単純と思われる TListbox.Items の例です.



図7
TListBox に読み込む CSV ファイルの内容

図8
実行結果

リスト5
CSV 文字列を TStrings 型変数に代入 - TListBox.Items の例
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  CSVファイルから文字列の読み込む例
//  カンマ区切りの文字列をTStrings型の変数に代入
//  ここではTListBox.Itemsとする
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LFileName : string;
  LStrList  : TStringList;
begin
  LFileName := ExtractFilePath(Application.ExeName) + 'ABC.csv';

  LStrList := TStringList.Create;
  try
    //データの読み込み
    LStrList.LoadFromFile(LFileName);

    //デリミタ(区切り文字)を指定して代入
    //デリミタの指定がない場合は,(カンマ)の指定と同じ
    ListBox1.Items.Delimiter := ',';
    ListBox1.Items.DelimitedText := LStrList.Text;
  finally
    FreeAndNil(LStrList);
  end;
end;

end.




05_文字列の置換用関数を使用した文字列の分割


文字列の置換用の関数を使用すれば,デリミタとして使用する任意の文字を改行文字に変換すことにより文字列を分解することができます.結果は,TStringList 等の TStrings の派生クラスの Text プロパティに代入します.
以下は ReplaceText と ReplaceStr 関数を使用する例です.これらの関数の違いは,大文字と小文字を区別するかの違いです.




3
図9
実行結果

リスト6
文字列の置換用関数を使用した文字列の分割
implementation

uses
  StrUtils;

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := 'delphi,文字列,分割,結合';
end;

//=============================================================================
//  指定文字をデリミタとして文字列を分割
//  文字列の置換用の関数を使用する例
//
//  usesにStrUtlisが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText    : string;
  LStrList : TStringList;
  LoopCnt  : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := Edit1.Text;
    LStrList.Text := StrUtils.ReplaceText(LText, ',', sLineBreak);

    Memo1.Lines.Clear;
    for LoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LoopCnt] <> '' then Memo1.Lines.Add(LStrList[LoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

//=============================================================================
//  指定文字をデリミタとして文字列を分割
//  文字列の置換用の関数を使用する例
//
//  usesにStrUtlisが必要
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LText    : string;
  LStrList : TStringList;
  LoopCnt  : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := Edit1.Text;
    LStrList.Text := StrUtils.ReplaceStr(LText, ',', sLineBreak);

    Memo1.Lines.Clear;
    for LoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LoopCnt] <> '' then Memo1.Lines.Add(LStrList[LoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;




06_複数のデリミタ文字を扱う例


Halbow 資料館の[任意のデリミタによる文字列の分離] の記事のコードでは,デリミタ文字を複数指定するようになっています.これは以下のようなコードとなっています.文字がデリミタ文字であるかの判定に,StrScan 関数を使用しています.



3
図10
設計時画面
図11
実行結果

リスト7
Halbow 資料館 に掲載されている,デリミタ文字を複数指定して分離する例
//-----------------------------------------------------------------------------
//  文字列を任意のデリミタ文字(複数)で分離する関数
//  デリミタ文字が文字列の場合
//  戻り値は分割した数
//
//  Str        : デリミタ文字を含む文字列
//  Delimiters : デリミタ文字列
//  SL         : デリミタで分割した文字列のリスト
//-----------------------------------------------------------------------------
function Split(const Str, Delimiters: String; SL: TStrings): Integer;
var
  SS  : String;
  i   : Integer;
  iSt : Integer;
begin
  SL.Clear;
  result := 0;
  if Length(Str) < 1 then exit;

  SS  := Str;
  iSt := -1;
  for i := 1 to Length(SS) do begin
    if StrScan(PChar(Delimiters), SS[i]) <> nil then begin
      if iSt <> -1 then begin
        SL.Add(Copy(SS, iSt, i - iSt));
        iSt := -1;
      end
    end else begin
      if iSt = -1 then iSt := i;
    end;
  end;

  if iSt <> -1 then SL.Add(Copy(SS, iSt, Length(Str)));
  result := SL.Count;
end;

//=============================================================================
//  Edit1の文字列を,Edit2の文字列のどれかをデリミタ文字として分離して取出す
//  結果はMemo1に表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  Label1.Caption := IntToStr(Split(Edit1.Text, Edit2.Text, Memo1.Lines));
end;

end.




07_複数のデリミタ文字を扱う例 - TSysCharSet でデリミタ設定


デリミタ文字を,文字セットで与える場合は,TSysCharSet で文字をセットし,CharInSet 関数で,その文字が文字セットに含まれているかを調べることができます.
この TSysCharSet には,漢字を含めることはできません.扱えるのは Ascii 文字の範囲だけとなります.上のサンプルで使用している StrScan 関数であれば,いわゆる「全角文字」も扱えます.


図12
実行結果

リスト8
TSysCharSet を使用し,デリミタ文字を文字セットで指定して,上のコード書き換えたコード
Split 関数のコードは,上のサンプルのコードと違うので注意
//-----------------------------------------------------------------------------
//  文字列を任意のデリミタ文字(複数)で分離する関数
//  デリミタ文字が文字セットで与えられた場合
//  戻り値は分割した数
//
//  Str        : デリミタ文字を含む文字列
//  Delimiters : デリミタとして使用する文字のセット
//  SL         : デリミタで分割した文字列のリスト
//-----------------------------------------------------------------------------
function Split(const Str: String; Delimiters: TSysCharSet; SL: TStrings): Integer;
var
  SS  : String;
  i   : Integer;
  iSt : Integer;
begin
  SL.Clear;
  result := 0;
  if Length(Str) < 1 then exit;

  SS  := Str;
  iSt := -1;
  for i := 1 to Length(SS) do begin
    if CharInSet(SS[i], Delimiters) then begin
      if iSt <> -1 then begin
        SL.Add(Copy(SS, iSt, i - iSt));
        iSt := -1;
      end
    end else begin
      if iSt = -1 then iSt := i;
    end;
  end;

  if iSt <> -1 then SL.Add(Copy(SS, iSt, Length(Str)));
  result := SL.Count;
end;

//=============================================================================
//  Edit1の文字列を,Delimetersで指定する文字のセットの何れか文字をデリミタと
//  して分離して取出す
//  結果はMemo1に表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
const
  Delimiters : TSysCharSet =['?', '/', '_', ',', ' ', '|'];
begin
  Memo1.Clear;
  Label1.Caption := IntToStr(Split(Edit1.Text, Delimiters, Memo1.Lines));
end;




08_複数のデリミタ文字を扱う例 - TStringHelper.Split 関数


Delphi XE3 では string 型の変数用のヘルパーであるTStringHelper が実装されています.
この TStringHelper を使用すると文字列の処理が容易に実現できます.以下のコードは Split メソッドを使用した文字列の分割の例です.


図13
実行結果

リスト9
TStringHelper.Split 関数を使用して,複数のデリミタで文字列を分割する例
//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := 'delphi&文字列,分割&結合';
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  SysUtils.TStringHelper.Split関数(Delphi Xe3以降)を使用する方法
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText        : string;
  LResultArray : TArray<string>;
  LoopCnt      : Integer;
begin
  LText := Edit1.Text;
  LResultArray := LText.Split([',', '&']);

  Memo1.Lines.Clear;
  for LoopCnt := 0 to Length(LResultArray) - 1 do begin
    Memo1.Lines.Add(LResultArray[LoopCnt]);
  end;
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  SysUtils.TStringHelper.Split関数(Delphi Xe3以降)を使用する方法
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LText         : string;
  LdelimiterSet : array [0 .. 1] of char;
  LResultArray  : TArray<string>;
  LoopCnt       : Integer;
begin
  LText := Edit1.Text;
  LdelimiterSet[0] := ',';
  LdelimiterSet[1] := '&';
  LResultArray := LText.Split(LdelimiterSet);

  Memo1.Lines.Clear;
  for LoopCnt := 0 to Length(LResultArray) - 1 do begin
    Memo1.Lines.Add(LResultArray[LoopCnt]);
  end;
end;




09_複数のデリミタ文字を扱う例 - ExtractHTTPFields 関数


セパレータとしてのデリミタ文字を,TSysCharSet で文字をセットする場合,ExtractHTTPFields 関数を利用することもできます.この関数を使用すると,以下のように,処理コードを非常に短くすることができます.


図14
実行結果

リスト10
HTTPApp の ExtractHTTPFields 関数を使用して文字列を分解する例
uses
  HTTPApp;

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := 'delphi&文 字列,分 割&結合';
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  ExtractHTTPFields関数を使用する例                                 
//
//  ExtractHTTPFieldsの使用にはusesにHTTPAppが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
const
  LDelimiters : TSysCharSet = [',', '&'];
  LWhiteSape  : TSysCharSet = [];
var
  LText    : string;
  LStrList : TStringList;
  LLoopCnt : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := Edit1.Text;
    HTTPApp.ExtractHTTPFields(LDelimiters, LWhiteSape, PChar(LText), LStrList);

    Memo1.Lines.Clear;
    for LLoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LLoopCnt] <> '' then Memo1.Lines.Add(LStrList[LLoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;




10_複数のデリミタ文字を扱う例 - ExtractStrings 関数


文字列の分割用の関数として ExtractStrings という関数もあります.その使用例です.



図15
実行結果

リスト11
ExtractStrings 関数を使用して文字列を分解する例
//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := 'delphi&文 字列,分 割&結合';
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  ExtractStrings関数を使用する例                                 
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText    : string;
  LStrList : TStringList;
  LoopCnt  : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := Edit1.Text;
    ExtractStrings(['?', '&'], [], PChar(LText), LStrList);
    Memo1.Lines.Clear;
    for LoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LoopCnt] <> '' then Memo1.Lines.Add(LStrList[LoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;




11_URL のパラメータを分割 - 日本語を含む URL はデコードが必要


HTTP サーバー等にリクエストする際,URL にパラメータを追加する時があります.このパラメータの最初の値は ? の後に書きます.2 番目以降は & で結合します.これらのパラメータの値を URL の文字列から取得する際の参考コードです.

パラメータそのものは,デリミタとして ? と & を指定すれば HTTPApp.ExtractHTTPFields 関数で取得できますが,日本語を含む URL は以下のようにエンコードされています.したがってデコードが必要です.日本語を含む URL のデコードには Indy の TIdURI.URLDecode が使用できます.
下図とその下のコードは,以下の URL のパラメータを分割して表示する例です.


https://www.google.co.jp/search?source=hp&q=delphi+%E6%96%87%E5%AD%97%E5%88%97+%E5%88%86%E5%89%B2


[備考]
URL の文字列の取得ではなく,逆にブラウザに表示する URL はエンコードが必要ですが,多くのブラウザでは,以下のように URL に日本語があっても,アドレス欄にコピーして貼り付けると自動的にエンコードしてくれます.



図16
URL の文字列をデコードしない時の結果

図17
URL の文字列をデコードした時の結果

リスト12
URL のパラメータを分割 - 日本語を含む URL はデコードが必要
uses
  HTTPApp,
  IdURI;

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := 'https://www.google.co.jp/search?source=hp'
              + '&q=delphi+%E6%96%87%E5%AD%97%E5%88%97+%E5%88%86%E5%89%B2';
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  URLの文字列のパラメータを分解する例
//
//  ExtractHTTPFieldsの使用にはusesにHTTPAppが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
const
  LDelimiters : TSysCharSet = ['?', '&'];
  LWhiteSape  : TSysCharSet = [];
var
  LText    : string;
  LStrList : TStringList;
  LoopCnt  : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := Edit1.Text;
    HTTPApp.ExtractHTTPFields(LDelimiters, LWhiteSape, PChar(LText), LStrList);

    Memo1.Lines.Clear;
    for LoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LoopCnt] <> '' then Memo1.Lines.Add(LStrList[LoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

//=============================================================================
//  複数のデリミタで文字列を分割する
//  URLの文字列のパラメータを分解する例
//  日本語を含むURLの場合はURL文字列のデコードが必要
//
//  URLDecodeの使用にはusesにTIdURIが必要
//  ExtractHTTPFieldsの使用にはusesにHTTPAppが必要
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
const
  LDelimiters : TSysCharSet = ['?', '&'];
  LWhiteSape  : TSysCharSet = [];
var
  LText    : string;
  LStrList : TStringList;
  LoopCnt  : Integer;
begin
  LStrList := TStringList.Create;
  try
    LText := TIdURI.URLDecode(Edit1.Text);
    HTTPApp.ExtractHTTPFields(LDelimiters, LWhiteSape, PChar(LText), LStrList);

    Memo1.Lines.Clear;
    for LoopCnt := 0 to LStrList.Count - 1 do begin
      if LStrList[LoopCnt] <> '' then Memo1.Lines.Add(LStrList[LoopCnt])
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;