Reputation:
From the MSDN pages for StreamWriter and BinaryWriter you can clearly see the differences:
StreamWriter:
Implements a TextWriter for writing characters to a stream in a particular encoding.
And:
BinaryWriter:
Writes primitive types in binary to a stream and supports writing strings in a specific encoding.
I know that the most important feature of BinaryWriter is that it can wirte primitive types in binary, which can be more compact and efficient (consider writing the integer 23861398 - the binary writer would require 4 bytes, but the stream writer would require 8, 16, or even 32 depending on the encoding).
But when it comes to write strings, can we say StreamWriter and BinaryWriter are interchangeable?
Upvotes: 6
Views: 875
Reputation: 70691
From the BinaryWriter
documentation:
Writes a length-prefixed string to this stream in the current encoding of the BinaryWriter, and advances the current position of the stream in accordance with the encoding used and the specific characters being written to the stream.
and:
Length-prefixed means that this method first writes the length of the string, in bytes, when encoded with the BinaryWriter instance's current encoding to the stream. This value is written as an unsigned integer. This method then writes that many bytes to the stream.
For example, the string "A" has a length of 1, but when encoded with UTF-16; the length is 2 bytes, so the value written in the prefix is 2, and 3 bytes are written to the stream, including the prefix.
The StreamWriter
class does not write any string-lengths to the output. It just writes the text itself
Both do respect the encoding you have specified when you create the object. The actual text being written uses that encoding.
So depending on what you mean by "interchangeable", they either are, or they are not. I would say they are not, but if all you are looking at is the sequence of bytes that represents the text written itself, one might consider them to be.
To address your comment:
I'm new to BinaryWriter, so why it need to write length to the stream first? why not just write "real data" directly?
Unlike StreamWriter
, which only writes one kinds of data, BinaryWriter
can write all sorts of data, include raw bytes and various primitive types, to a single Stream
. When writing each of these, it needs a way of indicating where that particular section of data ends. That's so that BinaryWriter
's reading counterpart, BinaryReader
, has a way of knowing where each section of data ends.
For some things, it's simple, because the data item itself is fixed size. A System.Int32
is 4 bytes, a System.Int64
is 8, and so on. They're fixed-length, so when reading you just read the expected number of bytes.
But string
objects are variable length. There are two common approaches to handling this: prefixing the string with a count, or terminating the string with a null character ('\0'
). In-memory .NET strings are counted, not null-terminated, and so string objects can actually contain a null character, and so null-terminating the string doesn't work for storing a string in a file.
So the prefix with the count of bytes is used instead.
Upvotes: 4
Reputation: 1063338
No, they're absolutely not interchangeable. BinaryWriter
is an opinionated basic IO tool for writing to binary outputs; StreamWriter
is for writing text outputs. Any times that the output looks similar is purely incidental - they should absolutely not be used interchageably.
For strings, they will look similar, but that's simply because both are ultimately just using a text-encoding. The boilerplate around them is very different though (with the BinaryWriter
using length-prefix, etc).
If you're looking to use one as though it were the other: you're probably doing something very wrong. If you clarify what you're trying to do, we can probably offer guidance.
Upvotes: 3