Jump to content
• Advertisement

# [.net] BinaryWriter / Streams Question

This topic is 5412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

## Recommended Posts

First of all, don't be frightened off by the length of this post, I think this is a relatively simple problem, but I'm just being as precise as possible :) OK, I've got a few questions regarding the BinaryWriter class and other stream-related things. There is a good chance I'm doing something really wrong, so feel free to point it out if I am! I'm writing a series of small projects from which I hope to learn more about C# and .NET in general. My current project centres around creating a Text Editor which let you save text in a specific format - optionally encrypted / compressed. The following (pseudo) code demonstrate the part that is causing me bother. The function basically writes the text in a specific format to the given stream.
public void WriteTo (Stream stream)
{
BinaryWriter bw = new BinaryWriter (stream, Encoding.UTF8);

// Write the length of the text	string
bw.Write ((UInt32) this._plainText.Length);

// If the text is to be encrypted then write to the stream
// via a CryptoStream, otherwise just write straight to the
// stream.
Stream textStream;

if (this.encrypted)
{
// Create & Setup a CryptoStream and make it piggyback
// on the 'stream' argument
textStream = new CryptoStream (stream, ...);
}
else
{
textStream = stream;
}

// ?
}


You'll notice that it ends with a question mark. At this point I want to write the text contained in the class (this._plainText) to the stream represented by textStream. The problem is that the BinaryWriter is 'attached' to the stream passed into the function and there seem to be no way to change it to textStream. I have tried simply creating another BinaryWriter and attaching 'textStream' to that, but I don't think the stream likes to have two BinaryWriters attached to it at once. Instead, I could close the old BinaryWriter and simply create a new one. However, doing so would also close the stream that was attached to it, and there would be no way to reopen it from this function. I hope that makes sense. As I said, if I'm doing something wrong here then please say so. Also, if you need to know more information then I'll be glad to post what you ask for. Thanks

#### Share this post

##### Share on other sites
Advertisement
Can you more clearly say what it is exactly you want to do?

#### Share this post

##### Share on other sites
I probably could, yes! Rather than post my code (there is a lot of it), I'll try and go by example instead...

Lets say that if the first byte in a stream is equal to 0 then that indicates that the remainder of the stream is compressed. If the byte is non-zero then it is uncompressed.
private void ReadFrom (Stream input){    BinaryReader br = new BinaryReader (input);        Stream decompressor;    if (br.ReadByte () == 0)        decompressor = new HuffmanStream (input);    else         decompressor = input;    // How can I now tell the BinaryReader to read from the    // 'decompressor' stream rather than the 'input' stream    // that was originally assigned to it?}

It's probably a crude example but I think it demonstrates my problem pretty well. (You don't need to worry about the compression stream or anything since it is only an example)

Anyway, the question is commented in the code. I now need to tell to the BinaryReader to read from the decompressor stream. I've tried to simply create a new BinaryReader but this won't work - presumable because 'stream' is already attached to 'br'. And I can't close the BinaryReader because that would close the stream.

One solution which did seem to work is to simply do:
private void ReadFrom (Stream input){    BinaryReader br = new BinaryReader (input);        Stream decompressor;    if (br.ReadByte () == 0)        decompressor = new HuffmanStream (input);    else         decompressor = input;    br = new BinaryReader (decompressor);}

However, since I didn't close the original BinaryReader is doesn't look right to me...

I hope this made more sense!

#### Share this post

##### Share on other sites
Quote:
 // How can I now tell the BinaryReader to read from the // 'decompressor' stream rather than the 'input' stream // that was originally assigned to it?

Just change the order your do things in. You can read from the stream without wrapping it in a BinaryReader.

private void ReadFrom (Stream input){    Stream decompressor;    if (input.ReadByte () == 0)        decompressor = new HuffmanStream (input);    else         decompressor = input;    BinaryReader br = new BinaryReader (decompressor);}

Or if your prefer it short:
BinaryReader br = new BinaryReader((input.ReadByte() != 0)? new HuffmanStream(input):input);

#### Share this post

##### Share on other sites
Well, thanks for your reply but that was just an example - It's my fault, I tried to demonstrate my problem and ended up over-simplifying it.

My actual code is far more complex than reading a single byte from the stream, I have to read a few integers and strings before I get to the 'is it compressed or not?' part.

For this reason I still think the best approach is to alter the stream attached to the BinaryWriter - otherwise the code would become too cumbersome.

Can someone help me out with this? Again, if what I'm trying to do is stupid or just plain 'wrong' then please point it out!

#### Share this post

##### Share on other sites
Ok, the point is that if you are doing something generic that choses between multiple methods of doing something you probably don't want to rely on any one of those methods until you know what method you are going to use. There are many, solutions to your problem as I see it. Here are a few:

1: use fixed size/dynamic header and read it off the stream before you asign it to a text/binary/whatever reader. (if the header contains binary data use a BinaryReader around a MemoryStream to read it)

2: don't use the readers at all and just use the stream.

3: get the stream out of your binary reader (see BaseStream property) and read from it before your use the reader.

4: assign multiple readers to the stream (probably won't work or will have unexpected results unless you are sure that no buffering is going on). (You mau be able to use seek methods to get around this)

5: read the entire stream into a buffer and than devide it up and parse it or convert it to streams.

6: Open the stream read the header close it and open it again.

7: Seperate the header info from the stream (on disk or where ever it is).

8: Use some sort of pre-existing format/parser (XML? Serialized Data?) and just forget about all of this stuff.

etc... etc... etc...

There it probably no reason to modify the BinaryReader (which you really cannot do -- though you could make a subclass if you really felt like wasting your time.)
Method 1 will work.
Method 2 could be best: if a tool does not work for your problem do not use it.

#### Share this post

##### Share on other sites
Well, thanks for your reply. I'll look into using your 2nd method. However, I can't see how I could read integers without using a BinaryReader. A stream just allows you to read byte arrays, right? There is probably a way to convert these arrays to integers, but it seems a bit of a hack to me.

Of course, I'm by no means an expert. I'll look into it.

Thanks

#### Share this post

##### Share on other sites
It is actually mostly trivial to encode/decode integers and numeric types because they are always the same size. An integer is 32 bits or 4 bytes long so to read an integer just read 4 bytes and then shift and add them like so:
//conceptual:byte[] intData;//read it off the streamint result = 0;result += (intData[3] << 24);result += (intData[2] << 16);result += (intData[1] << 8);result += intData[0];

Or the easy way in .NET:
int result = BitConverter.ToInt32(intData,0);

#### Share this post

##### Share on other sites
Quote:
 Original post by BarguastThere is probably a way to convert these arrays to integers, but it seems a bit of a hack to me.

Actually, this is exactly what a BinaryReader does internally. :)

#### Share this post

##### Share on other sites
Yeah, but doing the conversion myself (as I think turnpast recommended) seems a bit unnecessary when it is what the BinaryReader is for.

I guess, being a relative beginner, that I'm just a little confused as to what these classes actually 'are'.

As far as I am aware the BinaryWriter, BinaryReader (etc.) classes are just concerned with formatting. If you pass an integer in, they will convert it to a byte array and then pass that on to the BaseStream. Is that basically right?

In which case, why do these classes have Close methods? Since they are only data converters then why would you need a method to 'close' them? Or is the Close method just a convinient way of closing the underlying stream? In which case, is it really necessary to ever 'Close' a BinaryReader/BinaryWriter if I can just close the stream myself?

Quite a few questions there, but hopefully they will clear this up for me.

Thanks!

#### Share this post

##### Share on other sites

• Advertisement
• Advertisement

• ### Popular Now

• 18
• 29
• 11
• 21
• 16
• Advertisement
×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!