using System; using System.IO; using System.Text; namespace NTERA.EmuEra.Game.EraEmu.Sub { //reader/writer共通のデータはreaderの方に /// /// 1808追加 新しいデータ保存形式 /// Reader と違ってWriterは最新の書き込み方式だけ知っていればよい /// WriteHeader -> WriteFileType -> ... -> WriteEFO /// internal sealed class EraBinaryDataWriter : IDisposable { public EraBinaryDataWriter(FileStream fs) { writer = new BinaryWriter(fs, Encoding.Unicode); } BinaryWriter writer; public void WriteHeader() { writer.Write(EraBDConst.Header); writer.Write(EraBDConst.Version1808); writer.Write(EraBDConst.DataCount); for (int i = 0; i < EraBDConst.DataCount; i++) { writer.Write((UInt32)0); } } public void WriteFileType(EraSaveFileType type) { writer.Write((byte)type); } /// /// システム用。keyなしでInt64を保存 /// /// public void WriteInt64(Int64 v) { //圧縮しない writer.Write(v); } /// /// システム用。keyなしでstringを保存 /// /// public void WriteString(string s) { writer.Write(s); } public void WriteSeparator() { writer.Write((byte)EraSaveDataType.Separator); } public void WriteEOC() { writer.Write((byte)EraSaveDataType.EOC); } public void WriteEOF() { writer.Write((byte)EraSaveDataType.EOF); } public void WriteWithKey(string key, object v) { if (v is Int64) { writer.Write((byte)EraSaveDataType.Int); writer.Write(key); writeData((Int64)v); } else if (v is Int64[]) { writer.Write((byte)EraSaveDataType.IntArray); writer.Write(key); writeData((Int64[])v); } else if (v is Int64[,]) { writer.Write((byte)EraSaveDataType.IntArray2D); writer.Write(key); writeData((Int64[,])v); } else if (v is Int64[, ,]) { writer.Write((byte)EraSaveDataType.IntArray3D); writer.Write(key); writeData((Int64[, ,])v); } else if (v is string) { writer.Write((byte)EraSaveDataType.Str); writer.Write(key); writeData((string)v); } else if (v is string[]) { writer.Write((byte)EraSaveDataType.StrArray); writer.Write(key); writeData((string[])v); } else if (v is string[,]) { writer.Write((byte)EraSaveDataType.StrArray2D); writer.Write(key); writeData((string[,])v); } else if (v is string[, ,]) { writer.Write((byte)EraSaveDataType.StrArray3D); writer.Write(key); writeData((string[, ,])v); } } #region private private void m_WriteInt(Int64 v) { //セーブデータ容量の爆発を避けるためにできるだけWrite(Int64)はしない if (v >= 0 && v <= Ebdb.Byte)//0~207まではそのままbyteに詰め込む writer.Write((byte)v); else if (v >= Int16.MinValue && v <= Int16.MaxValue)//整数の範囲に応じて適当に { writer.Write(Ebdb.Int16); writer.Write((Int16)v); } else if (v >= Int32.MinValue && v <= Int32.MaxValue) { writer.Write(Ebdb.Int32); writer.Write((Int32)v); } else { writer.Write(Ebdb.Int64); writer.Write(v); } } private void writeData(Int64 v) { m_WriteInt(v); } private void writeData(Int64[] array) { //配列の記憶。0が連続する場合には圧縮を試みる。 writer.Write(array.Length); int countZero = 0;//0については0が連続する数を記憶する。その他の数はそのまま記憶する。 for(int x = 0; x < array.Length; x++) { if (array[x] == 0) countZero++; else { if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } m_WriteInt(array[x]); } } //記憶途中で配列の残りが全部0であるなら0の数も記憶せず配列の終わりを記憶 writer.Write(Ebdb.EoD); } private void writeData(Int64[,] array) { int countZero = 0;//0については0が連続する数を記憶する。その他はそのまま記憶する。 int countAllZero = 0;//列の要素が全て0である列の連続する数を記憶する。列の要素に一つでも非0があるなら通常の記憶方式。 int length0 = array.GetLength(0); int length1 = array.GetLength(1); writer.Write(length0); writer.Write(length1); for(int x = 0; x < length0; x++) { for(int y = 0; y < length1; y++) { if (array[x,y] == 0) countZero++; else { if (countAllZero > 0) { writer.Write(Ebdb.ZeroA1); m_WriteInt(countAllZero); countAllZero = 0; } if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } m_WriteInt(array[x,y]); } } if (countZero == length1)//列の要素が全部0 countAllZero++; else writer.Write(Ebdb.EoA1);//非0があるなら列終端記号を記憶 countZero = 0; } writer.Write(Ebdb.EoD); } private void writeData(Int64[, ,] array) { int countZero = 0;//0については0が連続する数を記憶する。その他はそのまま記憶する。 int countAllZero = 0;//列の要素が全て0である列の連続する数を記憶する。列の要素に一つでも非0があるなら通常の記憶方式。 int countAllZero2D = 0;//行列の要素が全て0である行列の・・・ int length0 = array.GetLength(0); int length1 = array.GetLength(1); int length2 = array.GetLength(2); writer.Write(length0); writer.Write(length1); writer.Write(length2); for(int x = 0; x < length0; x++) { for(int y = 0; y < length1; y++) { for(int z = 0; z < length2; z++) { if (array[x,y,z] == 0) countZero++; else { if (countAllZero2D > 0) { writer.Write(Ebdb.ZeroA2); m_WriteInt(countAllZero2D); countAllZero2D = 0; } if (countAllZero > 0) { writer.Write(Ebdb.ZeroA1); m_WriteInt(countAllZero); countAllZero = 0; } if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } m_WriteInt(array[x,y,z]); } } if (countZero == length2) countAllZero++; else writer.Write(Ebdb.EoA1); countZero = 0; } if (countAllZero == length1) countAllZero2D++; else writer.Write(Ebdb.EoA2); countAllZero = 0; } writer.Write(Ebdb.EoD); } private void writeData(string v) { if (v != null) writer.Write(v); else writer.Write(""); } private void writeData(string[] array) { int countZero = 0; writer.Write(array.Length); for(int x = 0; x < array.Length; x++) { if (array[x] == null || array[x].Length == 0) countZero++; else { if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } writer.Write(Ebdb.String); writer.Write(array[x]); } } writer.Write(Ebdb.EoD); } private void writeData(string[,] array) { int countZero = 0; int countAllZero = 0; int length0 = array.GetLength(0); int length1 = array.GetLength(1); writer.Write(length0); writer.Write(length1); for(int x = 0; x < length0; x++) { for(int y = 0; y < length1; y++) { if (array[x,y] == null || array[x,y].Length == 0) countZero++; else { if (countAllZero > 0) { writer.Write(Ebdb.ZeroA1); m_WriteInt(countAllZero); countAllZero = 0; } if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } writer.Write(Ebdb.String); writer.Write(array[x,y]); } } if (countZero == length1) countAllZero++; else writer.Write(Ebdb.EoA1); countZero = 0; } writer.Write(Ebdb.EoD); } private void writeData(string[, ,] array) { int countZero = 0; int countAllZero = 0; int countAllZero2D = 0; int length0 = array.GetLength(0); int length1 = array.GetLength(1); int length2 = array.GetLength(2); writer.Write(length0); writer.Write(length1); writer.Write(length2); for(int x = 0; x < length0; x++) { for(int y = 0; y < length1; y++) { for(int z = 0; z < length2; z++) { if (array[x,y,z] == null || array[x,y,z].Length == 0) countZero++; else { if (countAllZero2D > 0) { writer.Write(Ebdb.ZeroA2); m_WriteInt(countAllZero2D); countAllZero2D = 0; } if (countAllZero > 0) { writer.Write(Ebdb.ZeroA1); m_WriteInt(countAllZero); countAllZero = 0; } if (countZero > 0) { writer.Write(Ebdb.Zero); m_WriteInt(countZero); countZero = 0; } writer.Write(Ebdb.String); writer.Write(array[x,y,z]); } } if (countZero == length2) countAllZero++; else writer.Write(Ebdb.EoA1); countZero = 0; } if (countAllZero == length1) countAllZero2D++; else writer.Write(Ebdb.EoA2); countAllZero = 0; } writer.Write(Ebdb.EoD); } #endregion #region IDisposable メンバ public void Dispose() { if (writer != null) writer.Close(); writer = null; } #endregion public void Close() { Dispose(); } } }