2 using System.Collections.Generic;
5 using System.Threading.Tasks;
7 using System.Diagnostics;
12 /// SSD向けFileStream (ファイルの上書き保存時に、同じファイル内容を保存する場合は、ファイルの更新を行わない)
14 public class FileStreamSSD : MemoryStream, IDisposable
16 private string _filename;
17 private FileMode _mode;
18 private FileAccess _access;
19 private MemoryStream _ms_org = null;
20 private FileStream _fs;
21 private bool disposed = false;
24 /// (baseではなく)このクラスのClose()が実行されたかどうか
26 private bool bClosed = false;
31 public FileStreamSSD()
33 throw new ArgumentException( "FileStreamSSD: 引数のないコンストラクタは使用できません。" );
36 public FileStreamSSD( string path )
37 : this(path, FileMode.Create, FileAccess.Write)
40 public FileStreamSSD( string path, FileMode mode, FileAccess access )
43 if (mode != FileMode.Create)
45 throw new ArgumentException(mode.ToString() + "は、FileStreamSSD()でサポートしていません。");
47 if (access != FileAccess.Write)
49 throw new ArgumentException(access.ToString() + "は、FileStreamSSD()でサポートしていません。");
58 /// StreamのClose。元ファイルとのコンペアを行い、一致していればファイルの上書きをしない
60 public new void Close()
65 // 元ファイルがなければ、無条件に上書きコースへ。
66 if ( !File.Exists( _filename ) )
71 // まず、既存ファイルをMemoryStreamにコピー
73 using ( _fs = new FileStream( _filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete ) )
75 // 元ファイルとファイルサイズが異なる場合は、
76 if ( _fs.Length != this.Length )
82 _ms_org = new MemoryStream();
83 _fs.CopyTo( _ms_org );
89 if ( bSame ) // まだ新旧ファイルが一致している可能性があれば...
91 // MemoryStream同士のコンペア
92 _ms_org.Seek( 0, SeekOrigin.Begin );
93 this.Seek( 0, SeekOrigin.Begin );
97 while (this.Position < this.Length)
99 int dorg = _ms_org.ReadByte();
100 int dnew = this.ReadByte();
108 catch // ファイルサイズが同じ場合のみtry内に来るため、通常ここには来ないはずだが、念のためbSame=false側に倒しておく
113 if ( _ms_org != null )
119 this.Seek( 0, SeekOrigin.Begin );
121 // 元ファイルと新規ファイルが一致していない場合、新規ファイルで上書きする
124 Trace.TraceInformation( Path.GetFileName( _filename ) + ": 以前のファイルから変化があったため、書き込みを実行します。" );
125 using ( _fs = new FileStream( _filename, _mode, _access ) )
128 } // _fs will be closed and disposed, by using()
133 Trace.TraceInformation( Path.GetFileName( _filename ) + ": 以前のファイルから変化がなかったため、書き込みを行いません。" );
136 bClosed = true; // base.Close()の前にフラグ変更のこと。さもないと、無限に再帰実行される
142 #region [ Dispose-Finallizeパターン実装 ]
144 public new void Dispose()
146 this.Dispose( true );
147 GC.SuppressFinalize( this );
150 protected override void Dispose( bool disposing)
156 if (this._ms_org != null)
158 this._ms_org.Close();
159 this._ms_org.Dispose();
162 if (this._fs != null)
170 this.Close(); // Close()なしでDispose()された場合用 (DataContractSerializer経由だと、ここに来る)
172 this.disposed = true;
176 base.Dispose(disposing);
182 this.Dispose( false );