"0","1","2","3","4","aaa
bbb
ccc
ddd
"
"0","1","2","3,","4","eee
fff
ggg
"
上記のようなカンマ区切りでダブルクォーテションで囲まれデータを読み込むにはどうしたらよいのでしょうか?
VBでは
Input #1,s(0),s(1),s(2),s(3),s(4),Memo
と記述すると
s(0)="0"
s(1)="1"
s(2)="2"
s(3)="3"
s(4)="4"
Memo = "aaa・・bbb・・ccc・・・ddd
と取得できるのですが?
どなたかご教授ください。
TStringList
のヘルプをお読み下さい。
Delimiter
QuoteChar
CommaText
DelimitedText
単純にTStringListのCommaTextで処理しようとすると、
ファイル中の半角スペースも区切り文字と判断されてしまうので
注意が必要です。
裏技的なやりかたとしては、ExtractHTTPFields関数(uses節にHTTPApp
を追加)を使って、セパレータに,と"を指定するという手があります。
ためしにサンプルでテキストファイルを読み込んだのですが、改行で1レコードとして読み込んでしまいます。
読み込みたい方法は
"0","1","2","3","4","aaa
bbb
ccc
ddd
"
ここで1レコード
"0","1","2","3,","4","eee
fff
ggg
"
ここで1レコード
何ですが、無理なのでしょうか?
申し訳ありません。
ヘルプを見てもちんぷんかんぷんです。
この場合、TStringListは使えないと思います。
Quote単位で切り出して読込んでいくしかないでしょう。
なんか需要ありそうなので書いてみました。
procedure TForm1.messageStr(Line,delimit:integer; str:string);
var bufstr:string;
begin
bufstr:= inttostr(Line) + '行目-' +
inttostr(delimit) + '項-' +
str;
showmessage(bufstr);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ws,wcell:WideString;
lineIndex,delimitIndex:integer;
i:integer;
inDQ:boolean;
begin
ws:=Memo1.Text;
lineIndex :=0;
delimitIndex:=0;
inDQ:=False;
for i:= 1 to Length(ws)-1 do
begin
if ((ws[i]=#13) or (ws[i]=#10)) and (inDQ=False) then
begin
end else begin
wcell:=wcell+ws[i];
if ws[i]='"' then
inDQ:=not inDQ;
if (ws[i]=',') and (inDQ=False) then
begin
messageStr(LineIndex,delimitIndex,wcell);
inc(delimitIndex);
wcell:='';
end;
end;
if ((ws[i]=#13) and (ws[i+1]=#10)) and (inDQ=False) then
begin
messageStr(LineIndex,delimitIndex,wcell);
inDQ:=False;
wcell:='';
delimitIndex:=0;
inc(lineIndex);
end;
end;
end;
これはただ単に文字を区切ってるだけですが、改行入りテキストを扱えるようなStringListコンポーネントを作成するのも面白いかもしれませんね。
まぁ0から作るより、改行コードを別コードに置き換えて管理する方が作成は容易でしょうけど。
最後の一文字チェック抜けてます。スマセン。
> 改行入りテキストを扱えるようなStringListコンポーネントを作成するのも面白いかもしれませんね。
ちと欲しかったので、作ってみました。
Delphi 5 の TStringList.SetTextStr 及び、SetCommaText を参考にしています。
TStringListEx =class(TStringList)
protected
procedure SetTextStr(const aValue: String); override;
end;
implementation
procedure TStringListEx.SetTextStr(const aValue: String);
var
pChrs, rowStart: PChar;
rowString: String;
breakChar: Boolean;
begin
{更新開始}
BeginUpdate;
try
Clear;
pChrs := Pointer(aValue);
if pChrs <> nil then begin
while pChrs^ <> #0 do begin
{行開始}
rowStart := pChrs;
breakChar := not (pChrs^ in [#0, #$0A, #$0D]);
while breakChar do begin
if pChrs^ = '"' then begin
{引用符付き文字列を引用符なし文字列に変換して取得(pChrsのアドレスを進める)}
AnsiExtractQuotedStr(pChrs, '"');
end
else begin
Inc(pChrs);
end;
breakChar := not (pChrs^ in [#0, #$0A, #$0D]);
end;
SetString(rowString, rowStart, pChrs - rowStart);
{追加}
Add(rowString);
if pChrs^ = #$0D then Inc(pChrs);
if pChrs^ = #$0A then Inc(pChrs);
end;
end;
finally
{更新終了}
EndUpdate;
end;
end;
こんなトコかな?
ツイート | ![]() |