[VBScript]ファイルの入出力を同時に行う方法
以下の入力ファイルから以下の出力ファイルを作るアルゴリズムを考えていたのですが、
不明な点が出てしまい、アドバイスいただけないかと思い投稿しました。
不明な点は、掲題の通り、
「ファイルの入出力を同時に行うことが出来ないのではないか」という点です。
以下の入力ファイル形式を出力ファイル形式へ変換するには、
「セクション1」の「りんご」の行までは、入力ファイルを 1 行ずつ読み込んで
出力ファイルへ 1 行ずつ書き込めば良いと思います。
しかし、「セクション2」の「みかん」の「100」の文字列を出力ファイルへ書き込むには、
現在書き込み途中の出力ファイルの中を検索し、「みかん」の行が見つかったら
その隣に「,100」という文字列を書き込むという処理が発生します。
つまり、出力ファイルに対し、書き込みと読み込み(検索)を同時に行わければなりません。
このようなことが果たして可能なのか、以下のコードで確かめてみたのですが
エラーとなってしまいました。
やはり一旦出力ファイルをクローズするしかないでしょうか……?
■入力ファイル形式
・セクション1
いちご
みかん
りんご
・セクション2
みかん:100円
・セクション3
キウイ
バナナ
マンゴー
・セクション4
マンゴー:300円
■出力ファイル形式
いちご
みかん,100
りんご
キウイ
バナナ
マンゴー,300
■コード
Private Const overWrite = "True"
Private objFSO: Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Private objTextStream_out : Set objTextStream_out = objFSO.CreateTextFile(".\out.txt", overWrite)
objTextStream_out.WriteLine("いちご")
objTextStream_out.WriteLine("みかん")
objTextStream_out.WriteLine("りんご")
Private buffer_out : buffer_out = objTextStream_out.ReadAll()
No.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
この回答への補足
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
回答ありがとうございます。お返事遅くなりまして申し訳ございませんでした。
ADODB Stream オブジェクトは通常、DB 関係の処理に用いるものですが、
単なるファイル入出力にも活用できるとは思いつきませんでした。
有益なアドバイス感謝します。
コードを組んでみましたが(補足欄にアップしました)、
出力ファイル内でファイルを検索することは出来ても、
それを置換する処理はやはり難しそうです(書きかけ断念)。
今回、セクション 1, 2, 3, 4 が 1 つの入力ファイルに連続して書かれていると説明しましたが、
入力ファイル自体をセクション 1, 3 とセクション 2, 4 に分けることが可能なので、
セクション 1, 3 の情報を csv ファイル化し、セクション 2, 4 の情報も csv ファイル化して
マージする方法を取ることにしました。
この方法ですと、ADODB Stream オブジェクトの
ファイルポインタ操作が活用できることが確認できました。
サンプルコードは非常に参考になりました。ありがとうございました!
No.2
- 回答日時:
ファイル入出力というものを、改めて勉強して、FSOが何処までのものがやれるか、勉強のこと。
FSOの勉強から初めてファイル入出力の一般理論を勉強しないから、変な質問になる。基本的にテキストストリームはフィールドの内容を変えて、直にその場所に書き戻しが出来ない。
C言語などから来るストリームの考え方とは。
IBM大型事務系(および国内大型)OSなどなどは早くから色々なファイルシステムが考えらていた。
パソコンではこれらをあいまいにした上で説明がなされやすい。
昔のBasicにあったRandomAccess(固定長レコードで、レコード番号でアクセス)などはいまでは影が薄いようだ。
(ランダムアクセスとシーケンシャルアクセス)
ファイル構造(索引などを持ったファイル入出力)を持ったファイルと単純アクセスファイルなどの違い。
普通人は、検索などはADOのSQLなどに任せる場合が多く、自分で検索に便利なファイルシステムを自作する時代ではない。
パソコンに出てくるのは、ファイル構造は無いテキストファイルで
下記はすべて先頭からの順次処理になる。(シーケンシャルアクセス)
かつ最後からの逆戻り処理は普通は扱わない。
読み出し専用 これは議論ないだろう
書き込み専用 これもゼロの中身のファイルに一方的に順に書いていく。
追加書き込み専用 いま在るファイルの最後のレコードの次に書き込み追加を許すモード。Appendモード
書き込み修正 いま在るファイルの1部を修正して物理的に同じ場所に書き戻すということ。 これは通常しない・出来ない
其れで変更ない部分も新しいファイルに順次書き、修正する箇所は、アウトプットファイルの修正する箇所に来たとき、新しいファイル(アウトプットファイル)のその個所に修正したものを書く。修正前の部分は使わない。
ーーー
WriteLineメソッドはどれですか。無批判に使っているのでは。
ーー
以上は最終ファイル(通常ディスク)に記録する場合のことをいっているので、書く前段階として、フィールドの内容を示す変数の値の変動、フィールド数の変動は関係ないことだ。
だからその段階では変数にデータをとどめておいて、終了(確定)時に書き出せば済むことでは在る。
ーー
>セクション2
セクションという言葉はコンピュター界では良く出てきます。
突然質問で使っても何の意味で言っているのか判らない、。難しい言葉を無批判に使わないこと。
ーー
質問者は、上記に出てきた語句を中心に、WEBで照会でもして、勉強し、頭を整理してから質問すべきように思う。
この回答への補足
失礼ですが、あなたは結局、私の質問には答えられるのでしょうか?
こちらとしては FileSystemObject を絶対に使いたいという気持ちがあるわけではありません。
何らかの手段を用いて、書き込みと読み込みを同時に行いたいだけです。
No.1
- 回答日時:
「みかん: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 つ出力されると思います。
それを回避する方法をご存知でしたら補足いただけると幸いです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- C言語・C++・C# 至急お願いします。C言語で.imgのファイルを読み込んで1バイトづつ出力するプログラムを作りたいので 3 2023/01/16 22:49
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- PHP SQLとPHPの連結方法がわからないのでアドバイスお願い致します 1 2022/07/12 12:16
- Excel(エクセル) 【VBA】PDF出力に任意のファイル名前を付ける方法 3 2023/07/21 10:55
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Excel(エクセル) エクセルでSUMIFS関数で条件範囲の部分が#valueになる。 4 2023/04/28 12:42
- Visual Basic(VBA) VBA 参照先で選んだファイルをコピーし、出力先に別名で保存したい 8 2022/05/13 20:37
このQ&Aを見た人はこんなQ&Aも見ています
-
新NISA制度は今までと何が変わる?非課税枠の拡大や投資対象の変更などを解説!
少額から投資を行う人のための非課税制度であるNISAが、2024年に改正される。おすすめの銘柄や投資額の目安について教えてもらった。
-
コマンドプロンプトの「%1」と「%~1」の違いがわからない
その他(プログラミング・Web制作)
-
特定のファイルを他のプロセスが編集中か確認する方法
Visual Basic(VBA)
-
ReadLineでの読み出し行を指定する
Visual Basic(VBA)
-
-
4
VBSから別のVBS起動するとき変数を渡したい
Visual Basic(VBA)
-
5
バッチファイル 二つ上のディレクトリのパス取得
その他(プログラミング・Web制作)
-
6
vbscriptを用いて他のVBSファイルを実行
その他(プログラミング・Web制作)
-
7
Excelのセルにユーザー名を表示する方法
Excel(エクセル)
-
8
vbsのセル値の取得について
その他(プログラミング・Web制作)
-
9
vbsでテキストファイル内の文字列検索
Visual Basic(VBA)
-
10
ADODB.Streamで開いたファイルに追記する
その他(プログラミング・Web制作)
-
11
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
CSVファイルへの保存の際、デー...
-
ファイル名の先頭にアンダース...
-
グローバル変数のよくない使い...
-
マッチング処理
-
dataファイルをxtxファイルにす...
-
VBに、Cのincludeのようなもの...
-
アプリケーション終了時例外エ...
-
C#で、フォームのタイトル名を...
-
Word2016 「Microsoft Wordは...
-
テキストファイルの最終行を削...
-
BMP → AVI 作成について
-
最大値と最小値を求めるソース...
-
フレームワークについて
-
ドラッグアンドドロップでファ...
-
Excelマクロでの再読込み方法
-
Javascript で INI の読み書き
-
ファイルからサイズ不明の行デ...
-
機械学習初心者です。 本を読み...
-
インターネットショートカット
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
dataファイルをxtxファイルにす...
-
C言語初心者の質問失礼します。
-
csvファイルを開かずに文字を検...
-
テキストファイルの最終行を削...
-
ファイル名の先頭にアンダース...
-
大きいサイズのテキストファイ...
-
グローバル変数のよくない使い...
-
fopenできる上限の変更
-
ハッシュの計算時間について
-
VBに、Cのincludeのようなもの...
-
CSVファイルへの保存の際、デー...
-
分割コンパイルの#defineについて
-
VBAにてEXCEL以外のファイル(テ...
-
iniファイルに追記がしたいです。
-
ドラッグアンドドロップでファ...
-
SGファイルって何ですか?
-
同じ名前のファイルを作った場...
-
アドレス帳WABファイルをサンダ...
-
ダイアログボックスで複数フォ...
-
「VBScript」ADODB.Streamにお...
おすすめ情報