.NET 小物置き場
byte 配列以外の配列に対応した MemoryStream
通常の MemoryStream は、データを読み書きするために byte 配列に変換しないといけませんが
これはちょっと不便なので、int と short を扱えるように継承してみました。
データはリトルエンディアンな並び方で挿入していきます。
文字列も一応 UTF-8 のものだけ実験的に入れれるようにしています。
文字列は、\n の有無で終端チェックをしているので、終端に \n の含まれない文字列(行)は書けますが、読み込めません。
・これから先の更新でやるべきこと
普通の MemoryStream より例外のチェック項目が少ないので、追加してインターフェイスを統一する
UTF-8 以外の文字列を扱えるようにする
ビッグエンディアンに対応する
自由にコピーして使ってください。
エラーチェックはそれなりにしていますが、
不十分だと思うので、ソースの検証をしてから使ってください。
…って後で気づいたんですが、同じことしようと思ったら、
BinaryReader っていうクラスがあるんですねw
残念ながら、これいらないと思います。
これはちょっと不便なので、int と short を扱えるように継承してみました。
データはリトルエンディアンな並び方で挿入していきます。
文字列も一応 UTF-8 のものだけ実験的に入れれるようにしています。
文字列は、\n の有無で終端チェックをしているので、終端に \n の含まれない文字列(行)は書けますが、読み込めません。
・これから先の更新でやるべきこと
普通の MemoryStream より例外のチェック項目が少ないので、追加してインターフェイスを統一する
UTF-8 以外の文字列を扱えるようにする
ビッグエンディアンに対応する
自由にコピーして使ってください。
エラーチェックはそれなりにしていますが、
不十分だと思うので、ソースの検証をしてから使ってください。
…って後で気づいたんですが、同じことしようと思ったら、
BinaryReader っていうクラスがあるんですねw
残念ながら、これいらないと思います。
・図
ソースコード
//
// 更新日 2008/10/07
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Hikipuro.IO
{
/// <summary>
/// バッキング ストアとしてメモリを使用するストリームを作成します。
/// <para>
/// System.IO.MemoryStream の派生。
/// バイト単位以外のサイズの読み書き可能。
/// </para>
/// </summary>
class MemoryStreamM : MemoryStream
{
/// <summary>
/// 現在のストリームからバイトのブロックを読み取り、データを buffer に書き込みます。
/// </summary>
/// <param name="buffer">このメソッドが戻るとき、指定した配列の offset から (offset + count - 1) までの値が、現在のストリームから読み取られた文字に置き換えられています。</param>
/// <param name="offset">読み取りの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">読み取る最大要素数。</param>
public int Read(Int32[] buffer, int offset, int count)
{
int result = 0;
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[4] { 0, 0, 0, 0 };
int bytes;
bytes = this.Read(b, 0, 4);
result += bytes;
//Console.WriteLine("result[{0}] {1}", index, result);
buffer[offset + index] = b[0];
buffer[offset + index] |= (b[1] << 8);
buffer[offset + index] |= (b[2] << 16);
buffer[offset + index] |= (b[3] << 24);
if (bytes < 4)
break;
index++;
}
return result;
}
/// <summary>
/// 現在のストリームからバイトのブロックを読み取り、データを buffer に書き込みます。
/// </summary>
/// <param name="buffer">このメソッドが戻るとき、指定した配列の offset から (offset + count - 1) までの値が、現在のストリームから読み取られた文字に置き換えられています。</param>
/// <param name="offset">読み取りの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">読み取る最大要素数。</param>
public int Read(UInt32[] buffer, int offset, int count)
{
int result = 0;
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[4] { 0, 0, 0, 0 };
int bytes;
bytes = this.Read(b, 0, 4);
result += bytes;
//Console.WriteLine("result[{0}] {1}", index, result);
buffer[offset + index] = b[0];
buffer[offset + index] |= (UInt32)(b[1] << 8);
buffer[offset + index] |= (UInt32)(b[2] << 16);
buffer[offset + index] |= (UInt32)(b[3] << 24);
if (bytes < 4)
break;
index++;
}
return result;
}
/// <summary>
/// 現在のストリームからバイトのブロックを読み取り、データを buffer に書き込みます。
/// </summary>
/// <param name="buffer">このメソッドが戻るとき、指定した配列の offset から (offset + count - 1) までの値が、現在のストリームから読み取られた文字に置き換えられています。</param>
/// <param name="offset">読み取りの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">読み取る最大要素数。</param>
public int Read(Int16[] buffer, int offset, int count)
{
int result = 0;
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[2] { 0, 0 };
int bytes;
bytes = this.Read(b, 0, 2);
result += bytes;
//Console.WriteLine("result[{0}] {1}", index, result);
buffer[offset + index] = b[0];
buffer[offset + index] |= (Int16)(b[1] << 8);
if (bytes < 4)
break;
index++;
}
return result;
}
/// <summary>
/// 現在のストリームからバイトのブロックを読み取り、データを buffer に書き込みます。
/// </summary>
/// <param name="buffer">このメソッドが戻るとき、指定した配列の offset から (offset + count - 1) までの値が、現在のストリームから読み取られた文字に置き換えられています。</param>
/// <param name="offset">読み取りの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">読み取る最大要素数。</param>
public int Read(UInt16[] buffer, int offset, int count)
{
int result = 0;
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[2] { 0, 0 };
int bytes;
bytes = this.Read(b, 0, 2);
result += bytes;
//Console.WriteLine("result[{0}] {1}", index, result);
buffer[offset + index] = b[0];
buffer[offset + index] |= (UInt16)(b[1] << 8);
if (bytes < 4)
break;
index++;
}
return result;
}
/// <summary>
/// 現在のストリームからバイトのブロックを読み取り、データを str に書き込みます。
/// </summary>
/// <param name="str">データの書き込み元となる文字列。</param>
public int ReadLine(ref String str)
{
byte[] b = new byte[128];
long start = 0;
long end = 0;
bool found = false;
int bytes = 0;
start = this.Position;
end = start;
while ((bytes = this.Read(b, 0, 128)) != 0)
{
for (int i = 0; i < bytes; i++)
{
if (b[i] == '\n')
{
found = true;
end += i + 1;
break;
}
}
if (found == true)
break;
end += 128;
}
if (found == false)
{
this.Seek(start, SeekOrigin.Begin);
str = null;
return 0;
}
b = new byte[end - start];
this.Seek(start, SeekOrigin.Begin);
this.Read(b, 0, b.Length);
Encoding encode = Encoding.UTF8;
str = encode.GetString(b).TrimEnd('\n', '\r');
return (int)(end - start);
}
/// <summary>
/// バッファから読み取ったデータを使用して、現在のストリームに Int32 のブロックを書き込みます。
/// </summary>
/// <param name="buffer">データの書き込み元となるバッファ。</param>
/// <param name="offset">書き込むデータの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">書き込む最大要素数。</param>
public void Write(Int32[] buffer, int offset, int count)
{
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[4] { 0, 0, 0, 0 };
b[0] = (byte)((buffer[offset + index] >> 0) & 0xFF);
b[1] = (byte)((buffer[offset + index] >> 8) & 0xFF);
b[2] = (byte)((buffer[offset + index] >> 16) & 0xFF);
b[3] = (byte)((buffer[offset + index] >> 24) & 0xFF);
this.Write(b, 0, 4);
index++;
}
}
/// <summary>
/// バッファから読み取ったデータを使用して、現在のストリームに UInt32 のブロックを書き込みます。
/// </summary>
/// <param name="buffer">データの書き込み元となるバッファ。</param>
/// <param name="offset">書き込むデータの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">書き込む最大要素数。</param>
public void Write(UInt32[] buffer, int offset, int count)
{
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[4] { 0, 0, 0, 0 };
b[0] = (byte)((buffer[offset + index] >> 0) & 0xFF);
b[1] = (byte)((buffer[offset + index] >> 8) & 0xFF);
b[2] = (byte)((buffer[offset + index] >> 16) & 0xFF);
b[3] = (byte)((buffer[offset + index] >> 24) & 0xFF);
this.Write(b, 0, 4);
index++;
}
}
/// <summary>
/// バッファから読み取ったデータを使用して、現在のストリームに Int16 のブロックを書き込みます。
/// </summary>
/// <param name="buffer">データの書き込み元となるバッファ。</param>
/// <param name="offset">書き込むデータの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">書き込む最大要素数。</param>
public void Write(Int16[] buffer, int offset, int count)
{
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[2] { 0, 0 };
b[0] = (byte)((buffer[offset + index] >> 0) & 0xFF);
b[1] = (byte)((buffer[offset + index] >> 8) & 0xFF);
this.Write(b, 0, 2);
index++;
}
}
/// <summary>
/// バッファから読み取ったデータを使用して、現在のストリームに UInt16 のブロックを書き込みます。
/// </summary>
/// <param name="buffer">データの書き込み元となるバッファ。</param>
/// <param name="offset">書き込むデータの開始位置を示す buffer 内の要素数 オフセット。</param>
/// <param name="count">書き込む最大要素数。</param>
public void Write(UInt16[] buffer, int offset, int count)
{
int index = 0;
if (buffer.Length < offset + count)
throw new ArgumentException();
while (index < count)
{
byte[] b = new byte[2] { 0, 0 };
b[0] = (byte)((buffer[offset + index] >> 0) & 0xFF);
b[1] = (byte)((buffer[offset + index] >> 8) & 0xFF);
this.Write(b, 0, 2);
index++;
}
}
/// <summary>
/// 文字列を使用して、現在のストリームに バイト配列 のブロックを書き込みます。
/// </summary>
/// <param name="str">データの書き込み元となる文字列。</param>
public void Write(String str)
{
Encoding encode = Encoding.UTF8;
byte[] b = encode.GetBytes(str);
this.Write(b, 0, b.Length);
}
}
}