1

In java you can do this:

File file = new File(filepath);
PrintStream pstream = new PrintStream(new FileOutputStream(file));
System.setOut(pstream);

byte[] bytes = GetBytes();
System.out.write(bytes);

I want to do something similar in C#. I tried this but it didn't work:

StreamWriter writer = new StreamWriter(filepath);
Console.SetOut(writer);

byte[] bytes = GetBytes();
Console.Out.Write(bytes);

It looks like the main problem here is that the Write method does not accept an array of bytes as an argument.

I know that I could get away with File.WriteAllBytes(filepath, bytes), but I would like to keep the C# code as close as possible to the original, java code.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
John Smith
  • 4,416
  • 7
  • 41
  • 56
  • Why not just write the bytes to the `StreamWriter` directly? Bytes aren't written out to a console, strings are. The Java code you have is writing a string *representation* of the byte array to the console. You need to emulate the representation that Java uses and write that to the `StreamWriter`. – casperOne Jan 09 '13 at 17:28
  • Removing the `[java]` tag as the answer won't be about java. – Peter Lawrey Jan 09 '13 at 17:28
  • http://stackoverflow.com/questions/6397235/write-bytes-to-file – İsmet Alkan Jan 09 '13 at 17:29
  • http://stackoverflow.com/questions/1562417/read-binary-data-from-console-in – İsmet Alkan Jan 09 '13 at 17:31
  • 2
    In a nutshell, you’re simply not supposed to do that. Standard input and output are strictly for text, not for binary data. – Konrad Rudolph Jan 09 '13 at 17:33
  • Yes, indeed. And if you're not happy with the standard libraries, why don't you override these functions? – İsmet Alkan Jan 09 '13 at 17:36
  • I also tried doing Console.Out.Write(Encoding.Default.GetString(bytes)); but I ended up with a file that contained corrupted data. I guess I'll have to play with the StreamWriter object directly – John Smith Jan 09 '13 at 17:38
  • @JohnSmith, honestly, that's probably your best option. I realize that you want to make the code as 1-1 as possible with the original Java, but the fact is `Console` is not 1-1 with `System.out`. a `StreamWriter` is going to be more 1-1, logically, even if the *verbage* of the code differs. If you need the ability to hot-swap the output, you can just create a wrapper class for it and pass that around as your "out". – cwharris Jan 09 '13 at 17:43

3 Answers3

3

I know that I could get away with File.WriteAllBytes(filepath, bytes), but I would like to keep the C# code as close as possible to the original, java code.

The Java code does something you’re not supposed to do: it’s writing binary data to the standard output, and standard streams aren’t designed for binary data, they’re designed with text in mind. .NET does “the right thing” here and gives you a text interface, not a binary data interface.

The correct method is therefore to write the data to a file directly, not to standard output.

As a workaround you can fake it and convert the bytes to characters using an invariant encoding for the range of byte: Doesn’t work since the “invariant” encoding for .NET strings is UTF-16 which doesn’t accept every byte input as valid; for instance, the byte array new byte[] { 0xFF } is an invalid UTF-16 code sequence.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • That answers my question. However, I'd like to note that the workaround you proposed does not work: Console.Out.Write(Encoding.GetEncoding(1252).GetString(bytes)). Are you sure 1252 is the correct code page? – John Smith Jan 09 '13 at 17:46
  • 65001 is not working either. It's okay. I'll just forget about Console.Out. Thanks. – John Smith Jan 09 '13 at 17:51
  • @John Windows-1252 is an 8 bit encoding that should transform each byte into a unique character. Those characters are internally UTF-16 though, and the output happens as UTF-8 so I’m not surprised that it doesn’t work. I don’t think there’s a way to get it to work actually. – Konrad Rudolph Jan 09 '13 at 17:52
  • @IsmetAlkan No, it should be UTF-16 (I.e. just `Encoding.Unicode`) but unfortunately that won’t work because not all byte sequences are valid UTF-16. – Konrad Rudolph Jan 09 '13 at 17:53
0

Not just

File.WriteAllBytes(filepath, GetBytes())

or you could do,

using (var writer = new StreamWriter(filepath))
{
    var bytes = GetBytes();
    writer.BaseStream.Write(bytes, 0, bytes.Length)
};

Once you pass the StreamWriter to SetOut it exposes only the base TextWriter which does not allow access to the internal stream. This makes sense because Console is designed for providing output to the user. I guess its non standard to output arbritary binary to the console.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
0

There is also the method System.Console.OpenStandardOutput() which retrieves the binary standard output stream. You can use that to do something like

byte[] bytes = GetBytes();
Console.OpenStandardOutput().Write(bytes, 0, bytes.Length);
Hex
  • 23
  • 1
  • 6