• ベストアンサー

Delphi6 Delimiterの使い方

CSVファイルの処理で困っています。 ファイルから1行読んだ後、必要なカラムだけを 取得しようと思っています。 TStrings と DelimitedText を使って カンマで分割してくれるのは便利なのですが、 どうも半角スペースでも分割してしまうようです。 Delimiterプロパティで ',' と指定してるはず なのですが、空白も強制的に分割文字になって しまうんでしょうか? ソースのイメージとしては Var SL: Tstrings; で宣言して begin   ・・・   readln(target, line); { 1行読み込み }   SL := TStringList.Create;   SL.Delimiter := ',';   SL.DelimitedText := line; とやった上で SL[0]とかSL[1]とかで必要なカラムを取得しています。 宜しくお願いします。

noname#257070
noname#257070

質問者が選んだベストアンサー

  • ベストアンサー
  • honiyon
  • ベストアンサー率37% (331/872)
回答No.2

こんにちは、honiyonです。  お礼ありがとうございます(..  なるほど、CSV側が自動生成では、それに修正加えろ、というのは難しいかも知れませんね...(笑)  では、やはりCommaTextに代わるものを自分で作成する必要があると思います。  下記は何のエラーも想定していない基本的な独自処理のサンプルです。  メモ帳で適当に書いた非テストコードなので、あくまで考え方の参考程度にお願いします(^^;  また、半角カンマを含む文字列の処理は想定していませんのでご注意ください。 procedure SetCSV(var SL:TStringList; line:string); var   i : integer;   ans : string; begin   i := 0;   repeat     if line[i] = ',' then begin  //カンマ文字発見       SL.Add(ans);       ans := '';     end else begin //カンマ以外       ans := ans + line[i];     end;     inc(i);   until (length(line) < i); end;  このコードは、   readln(target, line); { 1行読み込み }   SL := TStringList.Create;   SetCSV(SL,line);  こんな風に使用します。  参考になれば幸いです(..

noname#257070
質問者

お礼

ありがとうございました。 サンプルを参考に自作のコードを作ってみました。 何とか解決ができたようです。 いろいろありがとうございました。

その他の回答 (2)

noname#14464
noname#14464
回答No.3

 TStringsじゃないですが・・・ 拙作、StrToken.pasのPickTokenメソッドならば、スペースを気にせず切り出しが出来ると思います。 String型変数に読み込みたいデータを入れて、それを第一引数に、第二引数に,を指定します。  実行すると、切り出された最初のトークンが戻り値として返り、引数に指定したString型変数の中身が、トークン切り出し後の残り文字列になります。 詳しくは添付サンプルファイルをご覧ください。  下記ページのリンクよりダウンロードできます。

参考URL:
http://takamichie.at.infoseek.co.jp/warehouse/units/index.html
noname#257070
質問者

お礼

ありがとうございました。 サンプルを参考に自作のコードを作ってみました。 何とか解決ができたようです。 いろいろありがとうございました。 Delphiの世界もいろいろサンプルコードがあるんですね。 何となく親切な人が多いジャンルだなぁと感じました。 自分も他の人の役に立てるように頑張ります!

  • honiyon
  • ベストアンサー率37% (331/872)
回答No.1

こんにちは、honiyonです。  文字列が " "で文字が囲まれていれば、正しく処理されます。取り扱おうとしているCSVには、文字列が " で囲まれていないのですね。一応CSVの規定としては、文字列は " "で囲むように指示されています。  ということでCSVに " "を付加すれば解決する問題ですが、それをせずに処理するには、一時的に他の文字に置き換えるか、独自でCSV処理するしかないと思います。  因みにカンマ区切りであれば、 SL.CommaText := line;  で OK です。 Delimiterは、カンマ以外で区切られているケースに対応する場合のみ使用するようにすると、ソースがちょっぴりスッキリするかもです。  参考になれば幸いです(..

noname#257070
質問者

お礼

ご回答ありがとうございました。 そうなんです。文字列が " " で囲われていない ファイルを操作しようとしているんです。 確かに、honiyon さんがおっしゃるとおり、 文字列が囲われていて、カンマ区切りであれば SL.CommaText := line; で済むんですが、そのCSVファイルはとある社内システムから 毎日自動的に生成されてくるので、それを変えるのは困難です。 何か良い方法はありませんか? もしくはサンプルソースなどがあると嬉しいです。 宜しくお願いします。

関連するQ&A

  • カンマをデリミタとするレコードを取得したい

    お世話になっております。 現在直面している問題に助言を頂けたらと思い質問をさせて頂きました。 もし、ご存じの方がいらっしゃいましたらご回答を宜しくお願い致します。 MySQLにて テーブルA カラム1  カラム2 1 AAA,BBB,CCC       2 BBB,DDD 3 CCC,DDD,EEE,FFF のようなレコードが入っているとします。 これをカラム2のカンマをデリミタとして分割した文字列でgroup byをしたような結果が欲しいと思っております。 希望結果 文字列 出現回数 AAA   1個 BBB   2個 CCC   2個 DDD  1個 EEE  1個 カンマで分けられている文字列の数に規則性はなく、何が入っているかわからない状態、 また、何個の文字列がカンマによって分割されているかわからない状態です。 AA,BB と2つの文字列がカンマ区切りで入っていることもあれば AA,BBB,CCCC,・・・・ と1000個の文字列がカンマ区切りで入っている状態です。 私が未熟なためか私の調べた限りではこのように取得する方法が見当たりませんした。 DBの構造に関しましては既に動いているサービス内のものですので変更することはできません。 以上、お手隙の際にご回答を宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • sed,awkでのデータ抽出方法

    教えてください。 awk,sed,シェルを使い、カンマ区切りのファイルの1カラム目と2カラム目をキーに、 あるファイルに含まれる行を削除するにはどうすればよいのでしょうか? 例) --aaa.csv-- 111,222,333,444 555,666,777,888 999,000,111,222 --file1.txt-- 111222 555666 の場合、aaa.csvより下記行のみほしい。 999,000,111,222 ご存知でしたら、ご教授ください。 よろしくお願いします。

  • カンマ区切りCSVファイルをVBAで読み込みたい

    こんにちは。EXCELのVBAに詳しい方、どうか教えてください! カンマ区切りCSVファイルをEXCELに読み込みたいのですが、 CSVファイルのデータが金額のため、データ自体にもカンマが含まれていて、 金額のカンマでも分割されてEXCELのセルに収まってしまいます。 データの区切りのカンマと、金額のカンマを区別して読み込む良い方法はないでしょうか。 とても困っているので、お解りになる方どうかご回答をお願いいたします。 ・CSVファイルのデータ   1,000 , 2,000 , 1,500 , 3,000 , 1,000 , 2,500 , 2,000  ↑金額のカンマでデータが分割されないように読み込みたいのですが・・・

  • VBA csvを100万行ずつ各シートに読み込み

     今晩は、質問させていただきます。どうぞよろしくお願いいたします。 環境:Win7 64bit SP1、 エクセル2010 でございます。  「1000万行×3列」のCSVファイルデータを、100万行ずつ シート1~10に振り分けたく悩んでおります。 ・エクセルは100万行しかありませんので、「一旦開いてから各シートに分割」という方法が使えませんし、 ・またReadLineいたしますと(1行ずつの方法しか存じませんので)時間がかかりそうですし、 何よりcsvファイルのカンマ記号も含め1行全てが、エクセルのひとつのセルに入ってしまうのでは、などと考えております。  何か良さそうな方法を思いつかれる方はおられませんでしょうか。 もしお詳しい方がいらっしゃいましたら,どうぞよろしくお願いいたします。

  • StringGridの中身をCSV形式で保存するには、保存の際に、ファイル拡張子を自動で「.csv」を付与するには?

    こんにちは。 StringGridの中身をCSVデータとして保存したいのですが、 その際に、『自分の好きな名前』で『デスクトップ』に保存できるようにしたいと考えています。 ソース1では、CSV形式での保存は行えるのですが、 名前をつけるやり方とデスクトップの指定方法が分かりません。 opendialog,savedialogを使うと思うのですが、 上手く組み合わせることが出来ずに困っています。 ソース2では、理想どおりの結果を出力できるはずなんですが、 実行すると空の結果が出力されます。どこが間違っているか分からず、困り果てています。 ・間違っている部分がどこか? ・保存する際に自動で端子に.csvを付与するにはどうすれば良いか? アドバイス頂けると助かります。 宜しくお願いしします。 -----------ソース1:------------------------------------------ procedure TForm2.GridSaveCSV(SGrid:TStringGrid; fName: String); var stList :TStringList; ARow :Integer; begin stList:=TStringList.Create; try for ARow:=0 to SGrid.RowCount-1 do stList.Add(SGrid.Rows[ARow].CommaText); stList.SaveToFile(fName); finally stList.Free; end; end; //CSVFileからStringGridへ読込み1 procedure TForm2.GridLoadCSV(SGrid:TStringGrid; fName:string); var stList: TStringList; ARow: Integer; begin stList:=TStringList.Create; try stList.LoadFromFile(fName); SGrid.RowCount:= stList.Count; for ARow:=0 to stList.Count-1 do SGrid.Rows[ARow].CommaText:= stList[ARow]; finally stList.Free; end; end; procedure TForm2.Button3Click(Sender: TObject); var fName: String; begin fName := 'csvtest.csv'; GridSaveCSV(StringGrid1,fName); end; -------------------------------------------------------------- -----------ソース2:------------------------------------------ procedure TForm2.Button8Click(Sender: TObject); var F : TextFile; Str : String; CellA,CellB,CellC,CellD,CellE : String; RowCNT : Integer; begin if not SaveDialog1.Execute then exit; if FileExists(SaveDialog1.FileName) then //↑ここのFileNameの使い方が良く分かりません>< //保存するときに、自動で.csvが付与されるようにしたいと思っています。 if Application.MessageBox('上書きしますか','注意',MB_YESNO ) = 7 then exit; //_ AssignFile(F,SaveDialog1.FileName); Rewrite(F); RowCNT := 0; try while not (StringGrid1.Cells[0,RowCnt] = '') do begin CellA := StringGrid1.Cells[0,RowCnt]; CellB := StringGrid1.Cells[1,RowCnt]; CellC := StringGrid1.Cells[2,RowCnt]; CellD := StringGrid1.Cells[3,RowCnt]; CellE := StringGrid1.Cells[4,RowCnt]; Str := Format('%s,%s,%s,%s,%s'[CellA,CellB,CellC,CellD,CellE]); // ↑この辺りが怪しいと思っています。 WriteLn (F,Str); Inc(RowCNT); end; finally CloseFile(F); end; end;

  • COPYコマンドの対象テーブルのフォールドを配列にした場合

    COPYコマンドを利用し、CSVファイルデータをテーブルへ登録しようと思うのですが、CSVファイルの1行のデータ数が300あります。300のフィールドを作成せずにフィールドを配列にしたみましたが、うまくいきません。配列では不可能でしょうか。 CSVファイルの1行のデータ数が多い場合は、何かよい方法がありますでしょうか。 CSVファイル No,Data1,Data2,....Data300 テーブル CREATE TABLE Data_log ( No int4, IN_data float8[] ) WITHOUT OIDS; SQL文 COPY Data_log from '" & ファイルパス & "' WITH DELIMITER ',';" 上の様に作成しましたが、SQLがうまくいきません。 どうぞ宜しくお願い致します。

  • VBSで空白の制御ができない

    勉強中の身ですが、行き詰ったので質問です。 VBSで2つのCSVファイルを読み込み、内容の異なるレコード、カラムを検知して差異があるレコードを取得させたいです。 CSV自体はカラムごとに「""」で囲ってありカンマ区切りです。 ADOで接続して各カラムごとの比較をする部分で両方とも空白のカラムを比較すると異なったときの分岐に進んでしまいます。 echoでそれぞれのデータを見ても「空白」に見え、実際のCSVも「""」となっています。 lenで長さ0で比較とかtrim後の比較をしてもどちらも同じに見えます。 どのようにすれば「同じ」データとして分岐処理を行えるでしょうか?

  • データ分割 正規表現だけで可能?

     都合のいい質問だと分かってて質問しています。  今、データの読み込みプログラムを作っています。  件数は12万件(11MB)です。 ・データはCSV形式になっており、区切りはカンマです。 ・"" で囲まれたカラムとそうでないカラムがあり、"" で囲まれたカラムの一部には、データとしてカンマが含まれていることがあります。 ・また、データにはエスケープシーケンスを含むことが許されており、 \" という文字は囲み記号であると認識してはいけません。  このようなルールのとき、    @data = split( /,/, $line );  というロジックでは分割できませんよね。  なんで、物凄い複雑なロジックで分割を行う xsplit という独自の関数を作って分割しています。  ところが、1行ごとにこの xsplit を使用しなければならないため、データが12万件もあると、読み込みだけで15~18秒もかかってしまいます。( split だと3秒で終わります)  で、少しでもこの時間を縮めるために、上記のルールを崩さずに split の /,/ の部分を変更するだけで分割を行うことはできないもんでしょうか。  何か思いついた方がいらっしゃいましたら、よろしくお願いします。 (ちなみに拡張モジュール類などの、環境によって動いたり動かなかったりするような物は使えないということでお願いします)

    • ベストアンサー
    • Perl
  • CSVからtxtに変換してのですが、ある行を境にちゃんとできない。

    (前置き) Outlook Express(以降OE)のアドレス帳をNOTESのアドレス帳にImportするときに、まず最初にOEのアドレス帳をExportします。 できたのがCSVファイルです。 このCSVファイルを拡張子を変更してtxtファイルに変更する必要があるので、そうしました・・・。 (症状) このtxtファイルですが、ある行から(具体的にはアドレス帳の16行目の人)から、",(コンマ)"が出なくなりました。 具体的には、 ,,,xxx@xxx.co.jp,,,,,,,,,,,,,,,,,,,,,,, が正しいのですが、ある行を境にして、 ,,,xxx@xxx.co.jp となってしまいます。 すごい不思議です。 手動でこのコンマを打てばいいのですが、なんせ600人分が後者になっていますので、かなり大変なんです。 なぜコンマがなくなるのでしょうか?どなたか教えて下さいませ。

  • マクロでのcsv読み込みについて

    エクセルのマクロにてcsvファイル(カンマ区切り)のデータを読み込むマクロを制作しているのですが、そのcsvファイルが1行めを2行目がデータ本体ではない為カンマの数が違い、openを使って読み込みを行うとうまくいきません。何かいい方法はないでしょうが。よろしくお願いいたします。

専門家に質問してみよう