ここから本文です

C#にて、StreamWriterでデータを書き込む場合、Closeされるまでのデータはどこに保...

suz********さん

2018/10/917:47:04

C#にて、StreamWriterでデータを書き込む場合、Closeされるまでのデータはどこに保持されている?

お世話になります

現在C#を勉強中の者です

一定時間ごとに5個のテキストファイルに、文字列を書きだすアプリケーションを作りました。

StreamWriterのインスタンスを5個保持して、それぞれに一定時間ごとにWriteしているのですが

StreamWriterで書き込んだデータは、Closeさせないと確定しないようで、Closeさせるまえにアプリケーションを終了すると、ファイルが残っていませんでした。

そこで疑問に思ったのですが、StreamWriterでデータを書き込む場合、Closeしてファイルを確定させるまでのデータってどこに保持しているんでしょう?

RAMメモリでしょうか?

もしそうだとすると、大容量のデータを書き込む場合は、書き込む前にOpenして、1行書き込んでまたCloseする、みたいな処理にしないとメモリオーバーフローを起こしたりするんでしょうか?

また、5個のインスタンスを保持して、テキストを書き込む方法だと、なんだか非常に時間がかかってそうです。
(実際に測定していませんが100文字書き込むだけで、5個全部で1~3秒くらいかかってそうです)

もっとよい方法があれば、アドバイス頂けますと幸いです。

閲覧数:
153
回答数:
2
お礼:
25枚

違反報告

ベストアンサーに選ばれた回答

abi********さん

2018/10/1617:46:04

[ファイルストリームのデータ保持場所の件]
ファイルストリーム等のストリーム系のデータ保持場所は、C#開発環境が用意したバッファ(すなわち、メモリ)に格納されます。



[メモリを意識する場合]
記憶媒体をファイルではなく、メモリにする場合は、メモリーストリームを使います。
メモリーストリームの基本的な使い方は、下記のサンプルにしまします。
下記の通り、ファイルストリームと殆ど同じ使い方です。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MemoryStreamSample01
{
___public partial class Form1 : Form
___{
______public Form1()
______{
_________InitializeComponent();
______}


______// ************************
______// フォーム呼び出し時のイベントプロシージャ
______// --- 初期化処理関係
______private void Form1_Load(object sender, EventArgs e)
______{

_________// 保存データーのデフォルトを設定
_________textBox1.Text = "あいうえお"; // 文字データー
_________label1.Text = "---";

______}


______// ************************
______// ボタンクリック時のイベントプロシージャ
______// --- データーの入力/書き込み/読み込み/表示
______private void button1_Click(object sender, EventArgs e)
______{
_________// データー書き込み
_________byte[] ByteArray;
_________WriteData(textBox1.Text, out ByteArray);

_________// データー読み込み
_________string StringData;
_________ReadData(ByteArray, out StringData);

_________// 読み取り結果をラベルに表示
_________label1.Text = StringData; // 文字データー表示


______}


______// ************************
______// データー書き込み用メソッド
______// 第1引数: 保存対象データーを指定
______// 第2引数: 指定データーをシリアル化して、それをバイト型配列として出力
______public void WriteData(string Data_In, out byte[] ByteArray)
______{

_________// メモリストリームをオープン
_________System.IO.MemoryStream mStr = new System.IO.MemoryStream();

_________// テキスト書き込みクラスを生成
_________System.IO.StreamWriter sw = new System.IO.StreamWriter(mStr, System.Text.Encoding.GetEncoding("shift_jis"));

_________// 入力データを書き込む
_________sw.Write(Data_In);

_________// フラッシュ
_________sw.Flush();

_________// メモリストリームに格納されているデーターをバイト型配列に設定
_________ByteArray = mStr.ToArray();

_________// メモリストリームをクローズ
_________mStr.Close();

______}


______// ************************
______// データー読み込み用メソッド
______// 第1引数: 対象データー(シリアル化して、バイト型配列にした物)を指定
______// 第2引数: 読み込みデーターを出力
______public void ReadData(byte[] ByteArray, out string Data_Out)
______{

_________// メモリストリームをオープン
_________System.IO.MemoryStream mStr = new System.IO.MemoryStream(ByteArray);


_________// テキスト読み込みクラスを生成
_________System.IO.StreamReader sr = new System.IO.StreamReader(mStr, System.Text.Encoding.GetEncoding("shift_jis"));


_________// 出力データを読み込む
_________Data_Out = sr.ReadToEnd();


_________// メモリストリームをクローズ
_________mStr.Close();

______}

___}
}



[メモリストリームの扱い方]
質問の件でのメモリストリームの扱いは、メモリストリームでデータ編集をして、最終的に作られたものをファイルストリームでファイル保存すると言うやり方もあります。
なお、メモリストリームは、コンストラクタで、バッファサイズを指定可能です。



[データが大きくなる場合]
データが大きくなる場合は、メモリマップドファイルと言うバッファを使います。
詳しくは、MemoryMappedFile のキーワードで検索して下さい。

  • abi********さん

    2018/10/1617:49:51

    [メモリマップドファイルの補足説明]
    メモリマップドファイルの場合は、記憶媒体をメモリでも、ファイルでも、どちらにも指定可能です。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

この回答は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜1件/1件中

blu********さん

2018/10/1200:09:11

>StreamWriterでデータを書き込む場合、Closeしてファイルを確定させるまでのデータってどこに保持しているんでしょう?

ソースが公開されているので読んでみてください。
https://referencesource.microsoft.com/#mscorlib/system/io/streamwri...

char配列のバッファに保持しているみたいですね。
バッファは固定長配列なので、スタックメモリですかね。

バッファサイズはコンストラクタで呼ばれるInitメソッド(197行から219行目)
をbufferSizeという引数で指定していますが、元をたどると恐らくデフォルト値である1024が指定されているかと思います。
(例えば124~126行目のコンストラクタを呼んでいるならDefaultBufferSize=1024がサイズになります)

421行目から444行目がWriteメソッドの中身ですが
CopyToメソッドで引数をcharBufferへコピーしています。

読むのが面倒臭くなったので適当解説ですが、
何となくFrushメソッドでファイルを書き込みしているみたいです。

①charのバッファからバイトのバッファ―にエンコード
②現在開いているファイル(Stream)のインスタンスからWriteメソッドを呼び出し、引数にバイトのバッファ―を渡している

この辺から調査がもっと面倒になり誰か調べていないのかとぐぐったら
こんな記事がありました。

http://soysoftware.sakura.ne.jp/archives/1246

ふーんって感じです。

ところで、5個もインスタンスを作成して何をなされるんですか?
何か悪い思想の匂いがします。

とりあえず、そんな感じ

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる