Kasper Hansen
Kasper Hansen

Reputation: 6557

Writing bytes to a file in C#

I have a BLOB from an Oracle database. In .NET it is of type OracleLob and has among them a Read and ReadByte methods.

int OracleLob.Read(byte[] buffer, int offset, int count)
int OracleLob.ReadByte()

So the Read method reads a sequence of bytes and ReadByte reads a single byte at a time. Here is my code:

OracleLob ol = (OracleLob) cmd.Parameters[1].Value; //her er filen!!

BinaryWriter binWriter = new BinaryWriter(File.Open(@"D:\wordfile.DOCX", FileMode.Create));
int currentByte = ol.ReadByte();

while (currentByte != -1)
{
   binWriter.Write(currentByte);
   currentByte = ol.ReadByte();
}

binWriter.Close();

But when I open wordfile.DOCX in Word, it says that the file is corrupt and cannot be opened. What am I doing wrong?

Upvotes: 3

Views: 7354

Answers (4)

Guffa
Guffa

Reputation: 700730

What's wrong with the code is that it's using an int value when writing the byte data to the BinaryWriter. It's using the overload that is writing an int instead of the one writing a byte, so each byte from the source will be written as four bytes. If you check the file size you see that it's four times as large as it should be.

Cast the value to byte so that the correct overload of the Write method is used:

binWriter.Write((byte)currentByte);

To do this more efficiently, you can use a buffer to read blocks of bytes instead of a single byte at a time:

using (FileStream stream = File.Open(@"D:\wordfile.DOCX", FileMode.Create)) {
  byte[] buffer = new byte[4096];
  int len = ol.Read(buffer, 0, buffer.Length);
  while (len > 0) {
    stream.Write(buffer, 0, len);
    len = ol.Read(buffer, 0, buffer.Length);
  }
}

Upvotes: 1

Marcelo Cantos
Marcelo Cantos

Reputation: 186078

BinaryWriter will output the int in some form of serialized manner. It won't write just a single byte. Use FileStream for this purpose, and use the byte[] versions of the read/write methods, since byte-at-a-time streaming is very slow.

Upvotes: 3

Øyvind Bråthen
Øyvind Bråthen

Reputation: 60724

A docx file is a OpenXml format file that is basically a series of xml files that is zipped down and renamed to docx. You can't just take a output from a database and write to a file and magically make it into a docx file.

Are you sure it's a docx file you are trying to make here? The only way I can see this working is if you serialized a docx file into the database, but then you have to make sure that it's de-serialized the exactly same way on "the way out", else the underlaying zip file will be corrupt, and the file cannot be opened.

Upvotes: 2

Neil Moss
Neil Moss

Reputation: 6848

currentByte is declared as an int, so the binary writer is writing 4 bytes for each write.

You need to cast currentByte as an actual byte:

binWriter.Write((byte) currentByte);

Upvotes: 1

Related Questions