• 締切済み

ファイルの排他

ログの出力/照会時の排他処理について、教えて下さい。 環境 言語:VC++/CLI OS:Win VISTA 前提 ログ出力 ・APL起動時にログファイルをオープンする。  (基本的にはオープンしっぱなし) ・メッセージ受信などイベント取得時にログに書き込む。  (複数スレッドからの書込み処理あり) ・最大行数に達したら、ファイルをクローズして、  新規にファイルをオープンしてそちらに書き込む。  (aaa_1.log, aaa_2.log,・・・という具合) ログ照会 ・画面からボタン押下で今まで書き込んだログを照会する。 ・ログ照会時はオープン→リード→クローズとなります。 質問 複数スレッドから書込み処理がある場合に備えて排他をかける 「読み込み時に書込み発生(EOFがおかしくなるとか)」や 「書込み時に読み込み発生(行の半端なところで表示されるとか)」など、バッティングした際を考慮した排他のかけ方 について注意点があればご教授頂きたいのですが・・・ 単純に以下のような実装イメージでよろしいのでしょうか? //////////////////////////////////// 書込み処理 //変数定義 StreamWriter^ sw = nullptr; 起動時 メソッド1 sw = gcnew StreamWriter( "TestFile.txt" ); 最大行数に達したら メソッド2 sw->Close(); sw = gcnew StreamWriter( "TestFile2.txt" ); //イベント発生 メソッド3 //排他処理 sw->WriteLine( "aaaa" ); //排他解除 //////////////////////////////////// //////////////////////////////////// 照会処理 //n=ファイルサイズを求めておく; //排他処理 StreamReader^ sr = gcnew StreamReader( "TestFile.txt" ); array<Char>^c = nullptr; while ( sr->Peek() >= 0 ) { c = gcnew array<Char>(n); sr->Read( c, 0, c->Length ); //ある理由でReadLineが                  //使えそうにないです                  //理由を説明すると                  //長くなりそうなので                  //省かせて下さい //画面出力領域 ← c } sr->Close(); //排他解除 //////////////////////////////////// 以上、宜しくお願い致します。

みんなの回答

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

Monitorクラスは WinAPIで言うところのCRITICALSECTIONで実装されているようです 同期の方法にいくつかの種類がありますので現状に即した物を選択すればいいでしょう 他の同期クラスとしてはSemaphoreというのもがあります ReaderWriterLockの実装が何なのかまでは調査できませんでした VC++付属のMSDNなどで『同期プリミティブ』等を検索してみましょう

isg7
質問者

お礼

ご回答ありがとうございます。 いろいろ調査してみます。

全文を見る
すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

同期用には MutexクラスかReadWriterLockクラス等がいいでしょう Mutexなら書き込みと読み込みで Mutexオブジェクトの取得に成功したら動作するようにするといった手順です ファイルを開きっぱなしにするのであれば Read処理の間に Writerに対してFlashなどを実行してバッファを書き出すなどの処理が必要でしょう

isg7
質問者

お礼

ご回答ありがとうございます。 現行システムではMonitorクラスというもので ロックしているようです。 上のMutexクラスやReadWriterLockクラスとは違うのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
noname#208124
noname#208124
回答No.1

読み側書き側共にFileStream使ってファイル開かないと ・Lock/Unlockメソッドが無い ・StreamReaderは常にFileShare.Readで開くので書き込み可能で開いてるファイルを開けない と思いますが

isg7
質問者

お礼

ご回答ありがとうございます。 確かにLock/UnlockはFileStreamのメソッドですね。 これを使って実装してみます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 結局 deleteしないとダメ? ファイナライザー万能主義は理解不足?

    安直に後始末はファイナライザ部に書いておけば、OKと思っていましたが、実行させると実行時エラー?になり正しくファイルに書き込めていません。リソースを解放するタイミングが理解できていないです。 書き込んでcloseすると確実ですが、何度もopenしないといけないので、オブジェクトの有効期間開きっぱなしで処理させて、オブジェクト消滅と共にクローズさせたいです。 以下、無理やり動作させたソースです。 この考え方は正しいでしょうか? /* ファイナライザに後始末処理を入れておけば すべてうまくいくと理解していたのですが そんな単純なものではないのでしょうか? */ #using <system.dll> using namespace System; using namespace System::IO; ref class Test_A { StreamWriter^ sw; // ファイルのオープン void open(void){ try { sw = gcnew StreamWriter( "test.log", true); } catch ( Exception^ ex) { Console::WriteLine("オープンエラー"); } } // ファイルのクローズ void close(){ if (sw){ sw->Close(); } } public: // コンストラク Test_A(){ sw = nullptr; open(); } // デストラクタ ~Test_A(){ this->!Test_A(); // ← これを書き、delete a;とすると、正しく書き込まれて変な例外ダイアログメッセージが表示されなくなる。 } // ファイナライザー !Test_A(){ close(); // ファイナライザで後処理すれば、万事OKではない?? } // ファイルの書き込み void Write(String^ log){ try { sw->Write(log); } catch ( Exception^ ex ) { Console::WriteLine("書き込みでエラー"); } } }; //------------------------------------- // メイン //------------------------------------- int main(void){ Test_A^ a = gcnew Test_A(); a->Write("delete aと、~Test_Aに処理を施さないと、正しく書き込めない。\n"); delete a; // ←これが無いと、変なダイアログメッセージが表示される、しかも正しく書き込めない。 return 0; }

  • 【VC++2005(CLR)】ファイル書き込み時、他でファイルが開かれていると落ちる

    いつも大変お世話になっています。 VC初心者です。 現在、ファイル書き込み処理で悩んでいます。 他のユーザがファイルをオープンしてたり、開こうとすると 落ちてしまいます。 たとえば、ファイルが開かれていることを検知して、 ユーザに「ファイルを閉じてください」とメッセージを出した後、 再度書き込み処理を実行できませんでしょうか。 (書き込み中は他のユーザからのアクセスを拒否させたいです。) 現在以下のようなソースを書いています。 //ファイルオープン System::IO::StreamWriter^ sw = gcnewSystem::IO::StreamWriter( path_w,false,System::Text::Encoding::Default); //ファイル書き込み String^ newData = "aaa"; sw->WriteLine(newData); //ファイルクローズ sw->Close(); お手数ですが、よろしくお願いします。

  • ファイルの排他について

    はじめまして。 初心者ですが、今非常に困っております。 RandomAccessFileを使用して、ファイルの排他をしたいのですが・・・。具体的に言うと、AがAAA.xmlをOPEN中にBがAAA.xmlをOPENしようとするとAがOPEN中なので、例外処理に飛ばしたいのです。いくら試みても例外処理に飛びません。 <例>(java version "1.3.1.05") try { raf = new RandomAccessFile("AAA.xml","rw"); // OPEN raf.writeBytes(111); // WRITE1 raf.writeBytes(222); // WRITE2 raf.writeBytes(333); // WRITE3 raf.writeBytes(444); // WRITE4 raf.writeBytes(555); // WRITE5 raf.close(); // CLOSE } catch(IOException e) { // 排他制御に失敗. リトライしたい System.out.println("別のプロセス?が使用中") }  心当たりのある方がいらしゃいましたら、ご協力お願い致します。

  • C# StreamReader,StreamWriter による文字化

    C# StreamReader,StreamWriter による文字化け お世話になります。 文字化けで悩んでいます。 Visual Studio 2008 C# にて、テキストファイルからデータを読んで別のテキストファイルに そのまま書き出す(もちろん実際の運用では加工するわけですが)処理で文字化けが起こります。 そのテキストファイル自身を C# で作れば問題はないのですが、メモ帳を使って書き込んだファイルでは 文字化けが起こります。 対処方法があれば教えてください。 以下はその実験に使ったコードです。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace ConsoleApplication5 { class Program { static void Main(string[] args) { // これは正常に書き込みできました StreamWriter sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.txt"); sw.WriteLine("これはてすとです。"); sw.WriteLine("This is test."); sw.Close(); // これも正常に読み込め、書き込みもできました StreamReader sr = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test.txt"); sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\newtest.txt"); while (!sr.EndOfStream) { sw.WriteLine(sr.ReadLine()); } sr.Close(); sw.Close(); // 次はあらかじめメモ帳で作ったファイルを読んで、別のファイルに書き出します // これが文字化けします sr = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\test2.txt"); sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\newtest2.txt"); while (!sr.EndOfStream) { string dat = sr.ReadLine(); sw.WriteLine(dat); Console.WriteLine(dat); } sr.Close(); sw.Close(); } } }

  • 【C#】作成したファイルに書き込みしたい

    開発環境はMicrosoft VisualC#2008です。 C#初心者です。よろしくお願いします。 現在、Form1とUserControl1を組み合わせてパズルゲームを作成中です。 Form1でボタンをクリックすると、クリックした日時を取得して、その日時をファイル名とするテキストファイルを作成することは出来ました。(例:20100115154717.txt) 今度は、そのファイルをUserControl1で開いて、書き込みをしていきたいのですが、エラーが出てしまい、この作成したファイルに書き込むことが出来ない状況です。 ※ちなみに、別のファイル(log_sample.txt)を指定したら書き込みは出来ました。 アドバイスよろしくお願いします。 <Form1.cs>一部抜粋 public string File_name { get { return this.file_name; } set { this.file_name = value; } } private void select_button_Click(object sender, EventArgs e) { //開いた時刻をファイル名に指定 DateTime dt = DateTime.Now; file_name = dt.ToString("yyyyMMddHHmmss"); //ログファイル作成・データ追加 StreamWriter sw = new StreamWriter(new FileStream"C:\\Documents and Settings\\My Documents\\log\\" + file_name + ".txt", FileMode.CreateNew)); } <UserControl1.cs>一部抜粋 //候補選択 private void label1_Click(object sender, EventArgs e) { Form1 f1 = this.Controls["Form1"] as Form1; DateTime dt = DateTime.Now; //ログ書き込み(日付、場所(ユーザーコントロール、ラベル名)、クリック(1)orダブルクリック(2)) StreamWriter sw = new StreamWriter(new FileStream("C:\\Documents and Settings\\My Documents\\log\\"+ f1.File_name +".txt", FileMode.Append)); sw.Write(dt.ToString()+","); sw.Write(this.Name +","); sw.Write("label1,"); sw.WriteLine("1"); sw.Close(); }

  • Visual C++ 2010 のファイル書き出し

    private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { String^ string1; string1=""; StreamWriter^ swriter1=gcnew StreamWriter("C:sample005.txt"); swriter1->WriteLine(string1); swriter1->Close(); } Visual C++ 2010 のWindowsフォームアプリケーションで、 ボタンのクリックからファイルを書き出したいのですが、上記ではエラーが出て動きません どのようにすれば良いのでしょうか?

  • VB.NET テキストファイルにデータを書き込み

    テキストファイル("c:\test.txt")に「かきくけこ」と全角5文字で1行のデータがあるとします。 このテキストファイルに「あいうえお」を先頭に追加で書き込みたいのですが、どうすればいいのでしょうか? あくまで「かきくけこ」を変数化せずファイルに直接、書き込む方法がある場合、教えてください。 'テキストファイルを開いたときの内容 あいうえお かきくけこ ちなみにですが、テキストファイル("c:\test.txt")に「かきくけこ」と全角5文字で1行のデータがあるとして、 末尾に「さしすせそ」を追加で書込みする方法は下記の通りでした。 'ファイルを書き込み用に開く、指定したファイルがない場合は作成する dim fsFile As System.IO.FileStream = _ System.IO.File.OpenWrite("c:\test.txt") 'StreamWriterオブジェクトを作成し、テキストデータが書き込めるようにする Dim sw As System.IO.StreamWriter = _ New System.IO.StreamWriter(fsFile) 'ファイルの末尾に移動する sw.BaseStream.Seek(0, System.IO.SeekOrigin.End) 'データを書き込む sw.WriteLine("さしすせそ") 'ファイルを更新する sw.Flush() 'ファイルを閉じる sw.Close() fsFile.Close() 'テキストファイルを開いたときの内容 かきくけこ さしすせそ

  • 一時ファイルをsavefileDialogを利用して保存するにはどのようにしたら良いのでしょうか?

    環境:VS2005 C# プログラム上でコメントアウトしてある様なやり方ではなく、 一旦、一時ファイルを作成しそのファイルをダイアログで保存先を任意のフォルダに保存したいのですがやり方はあるのでしょうか? OpenFileDialog ofd = new OpenFileDialog(); //一時ファイルを作成する string file_name = Path.GetTempFileName(); System.IO.StreamWriter writer = new StreamWriter(file_name); writer.WriteLine("tmptest"); writer.Close(); //ダイアログを表示 ofd.ShowDialog(); /*******************************▼コメントアウト System.IO.Stream stream; stream = ofdfilecommit.OpenFile(); if (stream != null) { //ファイルに書き込む System.IO.StreamWriter sw = new System.IO.StreamWriter(stream, 文字コード); sw.WriteLine("test"); //閉じる sw.Close(); stream.Close() } ********************************▲コメントアウト*/ //オブジェクトの破棄 ofd.Dispose(); ご協力お願いします。

  • 重複データを書き込まないようにするには?(VB)

    VB(2010)初心者です。 ボタンクリックで、テキストボックスに入力したデータをテキストファイルに 追加書き込みしていますが、同じデータは書き込めないようにしたいです。 下記コードにどのような記述を付け加えたら良いのでしょうか。 Dim fsFile As System.IO.FileStream = System.IO.File.OpenWrite("C:\List.txt") Dim sw As System.IO.StreamWriter = New System.IO.StreamWriter(fsFile) sw.BaseStream.Seek(0, System.IO.SeekOrigin.End) sw.WriteLine(TextBox1.Text) sw.Flush() sw.Close() fsFile.Close()

  • ASP.NETでStreamWriterクラスを使ってファイルに書き込む時にアクセスエラーが出ます

    ASP.NETでStreamWriterクラスを使い、abc.txt(中身は空です)に書き込みをしたいと思っていますが、Page_Loadイベントハンドラを使っても、ボタンClickイベントハンドラを使っても、ファイルにアクセスするときにエラーが出てしまいます。 ブラウザのエラーは以下の通りです。 '/kensyu' アプリケーションでサーバー エラーが発生しました。 パス "C:\abc.txt" へのアクセスが拒否されました。 また、イベントハンドラ内のコードは以下の通りです。 Dim sw As New System.IO.StreamWriter("C:\abc.txt") sw.WriteLine("Hello") sw.WriteLine("World") sw.Close() エラー内容を読む限りではabc.txtのプロパティにユーザを追加しろ、とあるように読めるのですが、追加ができません・・・ネットでも調べてみましたがわかりませんでした。解決方法をご存知の方がいらっしゃいましたら、どうぞよろしくお願いいたします。