- ベストアンサー
CSVファイルの中のEOF(0x1a)の削除
2008年に同様の質問をされている方がいらしたのですが、回答にあったURLが検索 できませんでしたので質問させていただく事にしました。 オフコンのデータをオフコンにあるソフトでCSVファイルに変換すると、最終行の先頭 に"0x1a"(EOF)が自動的に付加されてしまいます。そのCSVはパソコンのシステムで 使用するのですが、"0x1a"が入っている事で支障が出ます。 vbscriptでその"0x1a"を削除したいのですが、どのような記述をすれば削除できるの かがわかっておりません。アドバイスいただければ幸いです。宜しくお願い致します。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
以下は一例です。 Dim Stream 'ストリーム Dim RegExp '正規表現 Dim Text '文字列 '(1)ストリームをインスタンス化する Set Stream = CreateObject("ADODB.Stream"); '(2)ストリームを開き、各種設定を行う Stream.Open Stream.Type = 2 Stream.Charset = "SHIFT_JIS" '(3)ファイルからデータを読み込む Stream.LoadFromFile "D:\~\xxx.csv" '(4)文字列に取り出す Text = Stream.ReadText() '(5)正規表現をインスタンス化する Set RegExp = CreateObject("VBScript.RegExp") '(6)パターンを設定する RegExp.Pattern = "\x1A.*$" '0x1A以降全て '(7)パターンに一致する部分を除去する Text = RegExp.Replace(Text, "") '(8)ストリームの位置を先頭に戻す Stream.Position = 0 '(9)変換した文字列を書き込む Stream.WriteText Text '(10)現在の位置を終端にする Stream.SetEOS '(11)ファイルに保存する Stream.SaveToFile "D:\~\yyy.csv", 2 (12)後始末 Stream.Close Set Stream = Nothing Set RegExp = Nothing 【説明】 (2)ストリームの設定 .Typeには1(バイナリ型)か2(テキスト型)を設定します。 今回はCSVなのでテキスト型にします。 .Charsetには文字コードを設定します。もし、CSVが UTF-8とかEUC-JPのような文字コードなら、それを指定 します。規定はUnicodeです。 (3)ファイルからの読み込み パラメータには実際に使うファイルのパスを指定します。 (6)正規表現のパターン "\x1A.*$"は「1A以降終りまでの全文字」という意味です。 (7)パターンに一致する部分の除去 Replaceメソッドは置換ですが、置き換える文字列が空の 文字列なので、結果的に除去されます。 (8)(9)(10)ストリームへの書き込み 書き込む位置を先頭にするため、Positionに0を設定して から、編集したデータを書き込みます。 このままだとストリームのサイズは前のままなので、現在の 位置にEOS(End Of Stream)を置いて、サイズを詰めます。 (11)ストリームの内容をファイルに保存します。 第2パラメータの2は「上書き許可」という意味です。 (12)後始末 このままプログラムが終わるならやらなくてもイイです。 ただ、オブジェクトは使用後、速やかに解放するべきなので、 今後、何かに応用する場合のために記述しました。
その他の回答 (1)
- nda23
- ベストアンサー率54% (777/1416)
VBSでファイルを扱う場合、ADODB.Streamを使う方法と、 Scripting.FileSystemObjectを使う方法があります。 ファイルやディレクトリなどの削除、列挙やリネームを 行う場合は後者を使います。ファイルの読み書きは前者を 使う方がよいでしょう。 ADODB.Streamでは「1行ずつ読み込む」という観念はなく、 指定したバイト数を読み込むということしかできません。 指定を省略すると、サンプルで示したように全データを 読み込みます。 Scripting.FileSystemObjectはテキストファイルしか 扱えないので、ReadLineというメソッドで「1行づつ」の 読み込みは可能です。 ただ、ギガ単位でもなければStreamで一括読み込みし、 復帰改行で分割して、各要素毎に処理したほうがずっと 効率的です。 Dim ARY Dim TXT Dim STM '★中略 TXT = STM.ReadText '全件読み込み ARY = Split(TXT, vbNewLine) '復帰改行で分離 For Each TXT In ARY TXTを使った1行毎の処理 Next Split命令で、TXT内の復帰改行で分割した各行が配列に なってARYに格納されます。 For Each で配列の各要素を順に処理することができます。 この他、ADODB.Streamはバイナリファイルを扱ったり、 文字コードがShift_Jisでないテキストファイルでも扱う ことができるなどの利点があります。 また、ディスクのI/Oですが、ブロックデバイスはブロック 単位での入出力になります。HDではセクタ(512バイト)が 物理上の最小単位ですが、1セクタ読むのも1シリンダを 読むのも時間は殆ど変わりません。因みに1シリンダは物 にもよりますが63セクタ×255ヘッドが多いです。つまり、 小出しにI/Oするのはツマラナイ行為なんです。できるだけ I/O回数を減らせ、というのはこういう理由があるからです。 それと、C言語などでオブジェクトの処理をやってみると 分かりますが、COMモデルの処理は物凄く面倒なんですよ。 「1行ずつの読み込みをループして」という処理はこの 少量ずつのI/Oとメソッドの呼び出しが、繰り返し行われる という行為に他なりません。 私としては薦められないので、FileSystemObjectを使って ReadLineによる1行ずつの処理サンプルは掲載しません。 FileSystemObjectで検索すればサンプルは一杯、あります。
お礼
丁寧に説明していただき、どうもありがとうございました。 どうもオフコンでの処理がまず頭に思い浮かび、それを処理 する為にはと考えてしまうので、とにかく数多くこなし、学 習していかなくてはと思いました。 お礼が遅くなり、失礼致しました。
補足
詳しく説明まで付けていただき本当にありがとうございま す。 いただいた構文のファイル名の箇所を書き換えて実行し、 求めた形で出力する事ができました。 ADODB.streamを使った事がなく、これから勉強をしなけ ればならないのですが、この場をお借りしてもう一つ質問 をさせて下さい。 現在質問の処理をする為に一行ずつCSVを読み込み、先頭 の一文字目がある文字であれば書き出すという処理をさせ ています(DO~LOOPで行なっています)。 ADODB.streamでの処理の場合の考え方として、CSVファイ ルを一行ずつ読み込んで処理を行なうのではなく、全体の 中から該当する文字を消去して別のファイルへ書き出すと いう処理だという解釈でよろしいのでしょうか。 またADODB.streamで一行ずつ読んでの処理をするという 処理はできるのでしょうか? 度々で申し訳ございませんが、宜しくお願い致します。