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

文字列の上書き方法

環境/言語:[Xp C#2005Express Edition]
分類:[.NET]

こんにちは いつも勉強させて頂いてます。

環境 C#2005Express Edition パソコンOS xp

文字列の上書き方法を教えて下さい。

次のような処理で
foreach (Byte[] bh in ファイル){
 string data = Encoding.GetEncoding(932).GetString(bh)
 以下data処理
}

dataの文字数は5万程度と多いのでメモリ消費を抑える為「2回目のdataは1回目のdataを上書きしてくれれば良い」と考えますが .NET の仕様で上書きせずに新規に作成するようです。その為にどんどんメモリが減り、パフォーマンスの低下となります。
dataに上書きする(又はメモリの消費の少ない)方法はないでしょうか?
■No19103に返信(エツさんの記事)

> その為にどんどんメモリが減り、パフォーマンスの低下となります。

どこからも参照されていない領域はガベージコレクタが消してくれると思うので、メモ
リが減るということはあまり考えられないと思います。
(参照しっぱなしで次の領域を確保するという形だと困りますが)

「以下data処理」の部分でどういったことをしているのか不明ですが、そこで内容を書
き換えるような処理を行うのであれば、string ではなく StringBuilder に入れてしま
うという手もあると思います(どちらにしても一度は string を作りますけど)。

あとは重箱の隅をつつくようですが

 string data = Encoding.GetEncoding(932).GetString(bh)

 string data = Encoding.GetEncoding("Shift_JIS").GetString(bh);

のようにすべきだと思います(932だとマジックナンバーになってしまうので)。
■No19104に返信(ぽぴ王子さんの記事)
> ■No19103に返信(エツさんの記事)

早速の回答有難うございます。
foreach の繰り返し数が大変多くて1000回は軽く越えます。

data処理ではdata文字列の部分文字列を作成しデータベース(各フィールドは文字列)登録しています。

部分文字列は長いもので100文字、短いものは1文字です。
dataの殆どの部分を登録しますので各部分文字数の合計はdata文字数とほぼ等しく
ループ1回で5万+5万=10万文字を作成していることになります。

メモリが減ると言う表現は不味かったかもしれません。正確には処理時間が長いです。つぎのように仮定しました。
多くの文字列ができる ーー>メモリが減るーー>ガベージコレクタが頻繁に動作 −−>処理時間が長い

不要な文字列ができないーー>メモリが減らないーー>ガベージコレクタが動作しないーー>処理時間が短い

data処理部は何回か見直していますが、特にここが悪いという部分はありません。
しかし現実は遅いですから再検討しデータベース設計を含め効率的な処理を念頭に全て書き直す予定です。

今回はこの文字列のゴミが何とかならないかと思って質問した次第です。

StringBuilderでは string data = sb.ToString() で新規に文字列を作成しないでsbの内容自体を返しますがsb を使い回す為、処理の最後にsb.Remove(0, sb.Length - 1)として次のdataを読み込もうとするとこの時点で文字列が作成されます。(何故作成するの? 馬鹿 ) と言う訳で上手くいきません。


>  string data = Encoding.GetEncoding("Shift_JIS").GetString(bh);
有難うございます。早速使わせて頂きます。
2007/02/16(Fri) 21:16:30 編集(投稿者)
2007/02/16(Fri) 21:07:03 編集(投稿者)
2007/02/16(Fri) 20:50:51 編集(投稿者)

■No19106に返信(エツさんの記事)

自己レスです。

foreach (Byte[] bh in ファイル){
 string data = Encoding.GetEncoding(932).GetString(bh)
 以下data処理
}



foreach (Byte[] bh in ファイル){
 以下 変更済みdata処理
}
と変更します。

string data = Encoding.GetEncoding(932).GetString(bh) が余分なコードですね。これを消す事にします。
data処理にて
data文字列からの切り出しをやめて、バイト列bhから必要に応じてEncoding.GetEncoding("Shift_JIS").GetString(bh,Start,Length);を行います。
この方法ですと、大きな文字列ゴミはなくなり、小さな文字列ゴミだけになります。
小さな文字列ゴミは1回のループで約5万文字できますが、新しい小さなゴミの塊はガベージコレクタが消すのも早いですから、まあまあ大丈夫かなと(多少自信あり)。
またEncoding.GetEncoding("Shift_JIS").GetString(bh,Start,Length);を使用する回数もかなり増えますが文字列のSubString()が無くなるので良い勝負かなと。
文字の泣き別れには注意します。

#心変わりの理由
.NET の文字列は不変に逆らって上書きを検討しましたが、「上書きしてよいタイミングを常に考えるのは大変かな」と思い直しました。

どうも板汚して申し訳ありませんでした。
解決済み!

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