- ベストアンサー
[VBScript]ファイルの入出力を同時に行う方法
- [VBScript]ファイルの入出力を同時に行う方法について質問があります。具体的には、入力ファイルから出力ファイルを生成する際、同時に読み込みと書き込みを行うことができるかどうかが不明です。詳細な質問内容や現在のコードも掲載しています。
- 入力ファイル形式と出力ファイル形式を示し、アルゴリズムの一部を説明しています。特に、「セクション2」の「みかん」の行を探し、その隣に「,100」という文字列を追加する処理について疑問があります。
- 現在のコードでは、出力ファイルへの書き込みと読み込み(検索)を同時に行うことができないため、エラーが発生しています。最後に、「出力ファイルをクローズするしかないのか」という疑問を述べています。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ファイルの入出力方法はFileSystemObjectだけではありません。 ADODB.Streamオブジェクトを使うと、Positionプロパティを 操作することにより、任意の入出力ポイントに移動することが 可能です。この他、文字コードの変換やバイナリデータも扱う ことができます。勿論、それだけ面倒な制御が必要ですが、そこは 頑張るしかないですね。以下はサンプルです。 Dim X, T, C Set X = CreateObejct("ADODB.Stream") A.Open A.Type = 2 'テキスト形式を意味する。バイナリなら1 A.LoadFromFile "C:\~" 'ファイルを読み込むため開く A.Position = 0 'ファイルの先頭に位置付ける '---- 1行読み込み T = "" Do If A.EOS Then Exit Do '終端に達していれば終了 C = A.ReadText(1) '1文字読み込む If C = vbLf Then Exit Do '改行なら抜ける T = T & C ’文字を結合する Loop '---- ファイルを書き込む A.SaveToFile "C;\~", 2 '上書き許可を指定、不可なら1
その他の回答 (2)
- imogasi
- ベストアンサー率27% (4737/17069)
ファイル入出力というものを、改めて勉強して、FSOが何処までのものがやれるか、勉強のこと。 FSOの勉強から初めてファイル入出力の一般理論を勉強しないから、変な質問になる。基本的にテキストストリームはフィールドの内容を変えて、直にその場所に書き戻しが出来ない。 C言語などから来るストリームの考え方とは。 IBM大型事務系(および国内大型)OSなどなどは早くから色々なファイルシステムが考えらていた。 パソコンではこれらをあいまいにした上で説明がなされやすい。 昔のBasicにあったRandomAccess(固定長レコードで、レコード番号でアクセス)などはいまでは影が薄いようだ。 (ランダムアクセスとシーケンシャルアクセス) ファイル構造(索引などを持ったファイル入出力)を持ったファイルと単純アクセスファイルなどの違い。 普通人は、検索などはADOのSQLなどに任せる場合が多く、自分で検索に便利なファイルシステムを自作する時代ではない。 パソコンに出てくるのは、ファイル構造は無いテキストファイルで 下記はすべて先頭からの順次処理になる。(シーケンシャルアクセス) かつ最後からの逆戻り処理は普通は扱わない。 読み出し専用 これは議論ないだろう 書き込み専用 これもゼロの中身のファイルに一方的に順に書いていく。 追加書き込み専用 いま在るファイルの最後のレコードの次に書き込み追加を許すモード。Appendモード 書き込み修正 いま在るファイルの1部を修正して物理的に同じ場所に書き戻すということ。 これは通常しない・出来ない 其れで変更ない部分も新しいファイルに順次書き、修正する箇所は、アウトプットファイルの修正する箇所に来たとき、新しいファイル(アウトプットファイル)のその個所に修正したものを書く。修正前の部分は使わない。 ーーー WriteLineメソッドはどれですか。無批判に使っているのでは。 ーー 以上は最終ファイル(通常ディスク)に記録する場合のことをいっているので、書く前段階として、フィールドの内容を示す変数の値の変動、フィールド数の変動は関係ないことだ。 だからその段階では変数にデータをとどめておいて、終了(確定)時に書き出せば済むことでは在る。 ーー >セクション2 セクションという言葉はコンピュター界では良く出てきます。 突然質問で使っても何の意味で言っているのか判らない、。難しい言葉を無批判に使わないこと。 ーー 質問者は、上記に出てきた語句を中心に、WEBで照会でもして、勉強し、頭を整理してから質問すべきように思う。
補足
失礼ですが、あなたは結局、私の質問には答えられるのでしょうか? こちらとしては FileSystemObject を絶対に使いたいという気持ちがあるわけではありません。 何らかの手段を用いて、書き込みと読み込みを同時に行いたいだけです。
- infeeld
- ベストアンサー率37% (3/8)
「みかん:100円」という行を読み込んだ時、この文字列を「みかん,100」に変換して出力する方法はいかがでしょうか。 Dim fso Set fso = WScript.CreateObject("Scripting.FileSystemObject") '入力ファイルオープン Dim tsi Set tsi = fso.OpenTextFile(".\in.txt", 1) '出力ファイル作成 Dim tso Set tso = fso.CreateTextFile(".\out.txt", true) '入力ファイルを1件読み込みながら、出力ファイルに値を出力する。 Do Until tsi.AtEndOfStream = true Dim line line = tsi.ReadLine '(空行、「セクション」行)以外を処理対象とする。 If Len(line) > 0 And InStr(line, "セクション") <= 0 Then '「:」があったら「,」に変換 line = Replace(line, ":", ",") '「円」があったら削除 line = Replace(line, "円", "") '結果を書き込む tso.WriteLine(line) End If Loop tsi.Close tso.Close 上記の例は、入力ファイルと出力ファイル2つをオープンし、処理を行なっています。 オープンした1つのファイルに読み書きを同時に行なうのはわかりにくいため、私はあまりやりません。
お礼
回答ありがとうございます。お返事遅くなりまして申し訳ございませんでした。 いただいたアイディアについてなのですが、 この場合ですと、「みかん」に関する行が 2 つ出力されると思います。 それを回避する方法をご存知でしたら補足いただけると幸いです。
お礼
回答ありがとうございます。お返事遅くなりまして申し訳ございませんでした。 ADODB Stream オブジェクトは通常、DB 関係の処理に用いるものですが、 単なるファイル入出力にも活用できるとは思いつきませんでした。 有益なアドバイス感謝します。 コードを組んでみましたが(補足欄にアップしました)、 出力ファイル内でファイルを検索することは出来ても、 それを置換する処理はやはり難しそうです(書きかけ断念)。 今回、セクション 1, 2, 3, 4 が 1 つの入力ファイルに連続して書かれていると説明しましたが、 入力ファイル自体をセクション 1, 3 とセクション 2, 4 に分けることが可能なので、 セクション 1, 3 の情報を csv ファイル化し、セクション 2, 4 の情報も csv ファイル化して マージする方法を取ることにしました。 この方法ですと、ADODB Stream オブジェクトの ファイルポインタ操作が活用できることが確認できました。 サンプルコードは非常に参考になりました。ありがとうございました!
補足
Option Explicit Private Const forReading = 1 Private Const notCreate = "False" Private Const ASCIImode = 0 Private Const overWrite = "True" Private objFSO : Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") Private objUtility : Set objUtility = New Utility Private objTextStream_in01 Private objADODBStream_out01 Private filePath_in01 : filePath_in01 = ".\in01.txt" Private filePath_out01 : filePath_out01 = ".\out01.csv" Private buffer_in01 Private buffer_out01 : buffer_out01 = "" Private fruitName Private money Private chr Private flag_replaceMoney : flag_replaceMoney = False Set objTextStream_in01 = objFSO.OpenTextFile(filePath_in01, forReading, notCreate, ASCIImode) Set objADODBStream_out01 = WScript.CreateObject("ADODB.Stream") objADODBStream_out01.Charset = "UTF-8" objADODBStream_out01.Open While Not objTextStream_in01.AtEndOfStream buffer_in01 = objTextStream_in01.ReadLine() If InStr(1, buffer_in01, "・セクション") = 0 And buffer_in01 <> "" Then fruitName = objUtility.getFruitName(buffer_in01) If InStr(1, buffer_in01, "円") <> 0 Then objADODBStream_out01.Position = 0 Do If objADODBStream_out01.EOS Or flag_replaceMoney Then Exit Do End If chr = objADODBStream_out01.ReadText(1) If chr = vbLf And InStr(1, buffer_out01, fruitName) <> 0 Then money = objUtility.getMoney(buffer_in01) buffer_out01 = Replace(buffer_out01, "金額不明", money) flag_replaceMoney = True End If If chr <> vbLf Then buffer_out01 = buffer_out01 & chr Else buffer_out01 = "" End If Loop End If objADODBStream_out01.WriteText fruitName & ",金額不明" & vbCrLf objADODBStream_out01.Position = ??? flag_replaceMoney = False End If Wend