C#でバイナリファイルにテキストを書き、文字列と文字配列を書き込む間に書き込まれる量の違いを見ています。私はSystem.IO.BinaryWriterを使用して、書き込みが行われるとBinaryWriter.BaseStream.Lengthを見ています。これらは私の結果です:System.IO.BinaryWriterを使用した文字列とchar配列の相違点
なぜ3文字のASCII文字しか書いていないのに文字列のオーバーロードが4バイトを書き込むのか分かりません。誰もこれを説明できますか?
C#でバイナリファイルにテキストを書き、文字列と文字配列を書き込む間に書き込まれる量の違いを見ています。私はSystem.IO.BinaryWriterを使用して、書き込みが行われるとBinaryWriter.BaseStream.Lengthを見ています。これらは私の結果です:System.IO.BinaryWriterを使用した文字列とchar配列の相違点
なぜ3文字のASCII文字しか書いていないのに文字列のオーバーロードが4バイトを書き込むのか分かりません。誰もこれを説明できますか?
BinaryWriter.Write(string)
のドキュメントでは、このストリームに長さ接頭文字列を書き込むと記載されています。 Write(char[])
のオーバーロードには、そのようなプレフィックスはありません。
余分なデータは長さと思われます。
EDIT:
ただ、もう少し明確にするために、リフレクターを使用します。それはWrite(string)
方法の一部としてそこにコードのこの部分を持っていることがわかります。
this.Write7BitEncodedInt(byteCount);
それはバイトの最小限の数を使用して整数を符号化する方法です。短い文字列(日常的に使用する128文字未満の文字列)では、1バイトで表現できます。長い文字列の場合、より多くのバイトを使用し始めます。ここで
はあなたが興味を持っているだけの場合には、その関数のコードです:
protected void Write7BitEncodedInt(int value)
{
uint num = (uint) value;
while (num >= 0x80)
{
this.Write((byte) (num | 0x80));
num = num >> 7;
}
this.Write((byte) num);
}
このエンコーディングを使用して長さを前置した後、それが希望のエンコーディングの文字のためにバイトを書き込みます。 BinaryWriter.Write(string)
docsから
+1;あなたが**データを**読み込む方法を見ると、違いはさらに明確になります。 BinaryReader.ReadCharsを使用すると、読み込む数を指定する必要があります。 BinaryReader.ReadStringで長さ接頭辞を使用してこれを行います。 –
@Marc:優れた点。これらの2つは間違いなく互いに補完するために書かれていて、Write(文字列)メソッドは "ただし、どのようにしてそのデータを読むのですか?" –
実際に書かれたものを見ましたか?私はヌルターミネーターを推測するだろう。
:
はBinaryWriterの現在の符号化にこのストリームに長さ接頭文字列を書き込み、そして使用される符号化および特定の文字に応じて、ストリームの現在の位置を進めストリームに書き込まれます。
この現象はおそらくBinaryReader
を使用してファイルを読み取るときに文字列を識別できるようになるためです。 (例えば3Foo3Bar6Foobar
は "Foo"、 "Bar"、 "Foobar"という文字列に解析できますが、FooBarFoobar
にはできません)実際にはBinaryReader.ReadString
は正確にこの情報を使ってバイナリファイルからstring
を読み込みます。 BinaryWriter.Write(char[])
docsから
:
は、現在のストリームに文字列を書き込み、使用される符号化ストリームに書き込まれる特定の文字に応じて、ストリームの現在位置を進めます。
MSDNのドキュメントがどれくらい包括的かつ便利であるかを過度に説明するのは難しいです。必ず最初にチェックしてください。
既に述べたように、BinaryWriter.Write(String)は、文字列自体を書き込む前に、文字列の長さをストリームに書き込みます。
これにより、BinaryReader.ReadString()は文字列の長さを知ることができます。
using (BinaryReader br = new BinaryReader(File.OpenRead("data.dat")))
{
string foo1 = br.ReadString();
char[] foo2 = br.ReadChars(3);
}
ところで - あなたは自分のデータをシリアル化したい場合は、これを支援するためのAPIがある - 作り付けのシリアライザのいずれか、または使用可能なサードパーティ製のものの範囲があります。多くの場合、独自の読み取り/書き込みコードの大量書き出しよりもはるかに堅牢です。 –