DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C#でのファイル書き込み

環境/言語:[WindowsXP、C#]
分類:[.NET]

初めまして、C#初心者の者です。

さっそくですが、ファイルの書き込み処理について教えていただきたいのですが、
現在やろうとしていることは、一行一件のデータが数百件登録されているテキストファイル
から、任意の行を修正するという処理です。

実現方法として、
1.一時ファイルを作る
2.テキストファイルから一行ずつ読込み、修正行でなければそのまま読み込んだデータを
  一時ファイルに書き込む。修正行であれば修正データを一時ファイルに書き込む。
3.2の処理を全件分繰り返し、一時ファイルを完成させる。
4.一時ファイルを正規ファイルに置き換える。

という方法を行ったのですが、処理時間がかかり過ぎるため使用できません。
もっとスマートで高速な方法をご存知でしたらご教授よろしくお願いします。
こんにちは、たろうさん。

■No6410に返信(たろうさんの記事)
> 実現方法として、
> 1.一時ファイルを作る
> 2.テキストファイルから一行ずつ読込み、修正行でなければそのまま読み込んだデータを
>   一時ファイルに書き込む。修正行であれば修正データを一時ファイルに書き込む。
> 3.2の処理を全件分繰り返し、一時ファイルを完成させる。
> 4.一時ファイルを正規ファイルに置き換える。

実現方法はともかく、数万行を処理しても2, 3秒程度で済みましたが?
(数百程度ならほぼ一瞬で終わる...)
もしかして1レコード(1行)のカラム(文字数)が果てしなくでかいのでしょうか?

また、実装に使用している「モノ」がわかりません。
System.IO.FileStream, StreamReader, StreamWriterでしょうか?

> 処理時間がかかり過ぎるため使用できません。
> もっとスマートで高速な方法をご存知でしたらご教授よろしくお願いします。

短絡的な考えとしては、一時ファイルを作るのを止めて、指定位置までシークして修正する方法くらいでしょうかねぇ。
要するに、書き込む時間を(修正したい)1行にすれば大幅にタイムカットできるのではないかと。
■No6412に返信(java.lang.Nullpoさんの記事)
> こんにちは、たろうさん。

初めまして、java.lang.Nullpoさん。
返信ありがとうございます。

> 実現方法はともかく、数万行を処理しても2, 3秒程度で済みましたが?
> (数百程度ならほぼ一瞬で終わる...)
> もしかして1レコード(1行)のカラム(文字数)が果てしなくでかいのでしょうか?

いえ、700バイト程度なのでごく普通だと思います。
ただ、このプログラムを動かしているものが、少々特殊なPDAでして、ファイルの
読込みをメモリカードから直接行っていますのでその為かもしれません。
テキストファイルを本体にコピーしてもう一度確認してみます。

>
> また、実装に使用している「モノ」がわかりません。
> System.IO.FileStream, StreamReader, StreamWriterでしょうか?

はい。StreamReader, StreamWriterを使用しています。


> 短絡的な考えとしては、一時ファイルを作るのを止めて、指定位置までシークして修正する方法くらいでしょうかねぇ。
> 要するに、書き込む時間を(修正したい)1行にすれば大幅にタイムカットできるのではないかと。

私もこの方法をずっと調べていたのですが、見つけることができませんでした。
ぜひやり方を教えてもらえないでしょうか?
よろしくお願いします。
2004/09/30(Thu) 14:38:42 編集(投稿者)

■No6414に返信(たろうさんの記事)
> いえ、700バイト程度なのでごく普通だと思います。
> ただ、このプログラムを動かしているものが、少々特殊なPDAでして、ファイルの
PDAでしたか...。ちょっとキツイかもしれませんね。

> 読込みをメモリカードから直接行っていますのでその為かもしれません。
> テキストファイルを本体にコピーしてもう一度確認してみます。
メモリカードを壊さないためにもその方がいいですよ。
直接読み書きしてると、壊れやすいですからね。(って昔の話か...)

> 私もこの方法をずっと調べていたのですが、見つけることができませんでした。
> ぜひやり方を教えてもらえないでしょうか?
> よろしくお願いします。

この方法、StreamReader, StreamWriterではとても難しいのです。
Seek([offset], current)で開始位置を設定することはできるのですが、
余ってしまった文字を削除しなくてはならなかったり、
全角文字を考慮すると、単純に文字数で計算できなかったり...
今やってみたのですが、複雑すぎて "ある方法" より遅くなることが判りました。

ちなみに、"ある方法" というのは、大したことではなく、

 1. 一気にReadToEnd()メソッドで全て読み込む。
 2. 修正行を探しつつ、修正行を置き換える
 3. 一気に保存

これならば、別ファイルを作らなくても良い(作った方が安全でしょうが)です。
ちなみに、そのファイルの構造がどうなっているか判らないのですが、
↓は少しは参考になるかもしれません。

http://dobon.net/cgi-bin/vbbbs/srch.cgi?no=0&word=5298&andor=and&logs=1.txt&PAGE=20&ALL=1

Arrayの部分を削除して、修正部分を判断して置き換える方法にするとそんな感じになると思いますが、
それでもあまりスピード変わらないような気がします...

どうしても、処理に時間がかかるようでしたら、非同期で読み込んでその間を経過表示すると親切です。

# 自分 < なんか、見当違いのレスしかしてないなぁ...



■追記

 ただ、これを見る限り、

> いえ、700バイト程度なのでごく普通だと思います。

 流石にPDAでも、どんな方法に関わらず一瞬で終わる処理だと思うのですが...
>>いえ、700バイト程度なのでごく普通だと思います。
>
>  流石にPDAでも、どんな方法に関わらず一瞬で終わる処理だと思うのですが...

私もそう思うのですが、3〜4秒掛かってしまいます。
ボタン押下で次の情報を表示するのには少々長すぎます。


> この方法、StreamReader, StreamWriterではとても難しいのです。
> Seek([offset], current)で開始位置を設定することはできるのですが、
> 余ってしまった文字を削除しなくてはならなかったり、
> 全角文字を考慮すると、単純に文字数で計算できなかったり...

いろいろと調べていただきありがとうございました。

> どうしても、処理に時間がかかるようでしたら、非同期で読み込んでその間を経過表示すると親切です。

最終手段として考慮してみます。

教えていただいた方法をいくつか試してみたいと思います。
どうもありがとうございました。

アドバイスの通り、初めに読み込んでおき必要時のみ一気に書き込む
方法で解決しました。

どうもありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板