Clear Stream

S

shapper

Hello,

I am converting a pdf file page to a Bitmap, using a commercial
library, and then to a Byte[].

MemoryStream stream = new MemoryStream();
stream.Write(file, 0, file.Length);
PDFFile pdf = PDFFile.Open(stream);
Bitmap image = pdf.GetPageImage(page, 72);

??? Clear Stream to have image now.

image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
Byte[] data = new Byte[stream.Length];
stream.Dispose();

First I load the pdf file into a stream, i get the page and now I need
to use a stream to convert it to byte?

Can i empty the stream and use it again instead of using another
stream?
How can I do that?

I was thinking in use stream.Flush(); but it says about Flush:
"overides flush so no action is performed"

I want to perform more actions so I am not sure if this is the correct
option.

Thanks,
Miguel
 
M

Mythran

shapper said:
Hello,

I am converting a pdf file page to a Bitmap, using a commercial
library, and then to a Byte[].

MemoryStream stream = new MemoryStream();
stream.Write(file, 0, file.Length);
PDFFile pdf = PDFFile.Open(stream);
Bitmap image = pdf.GetPageImage(page, 72);

??? Clear Stream to have image now.

image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
Byte[] data = new Byte[stream.Length];
stream.Dispose();

First I load the pdf file into a stream, i get the page and now I need
to use a stream to convert it to byte?

Can i empty the stream and use it again instead of using another
stream?
How can I do that?

I was thinking in use stream.Flush(); but it says about Flush:
"overides flush so no action is performed"

I want to perform more actions so I am not sure if this is the correct
option.

Thanks,
Miguel

There is no method to empty or clear the contents, although you can do that
yourself. I do not recommend this, instead I would just create another
MemoryStream instance. From the snip you posted, I don't see any dispose
calls....the example below uses the 'using' statement to automatically
handle disposing of the objects.

byte[] bytes;
using (MemoryStream stream = new MemoryStream()) {
stream.Write(file, 0, file.Length);
PDFFile pdf = PDFFile.Open(stream); // Does this object implement
IDisposable?
using (MemoryStream stream2 = new MemoryStream()) {
using (Bitmap image = pdf.GetPageImage(page, 72)) {
image.Save(stream2, System.Drawing.Imaging.ImageFormat.Png;
}
bytes = stream2.ToArray();
}
}
// Do what you need with the byte-array here.

HTH,
Mythran
 
P

Peter Duniho

shapper said:
[...]
Can i empty the stream and use it again instead of using another
stream?
How can I do that?

You can. Just call Stream.SetLength(), passing 0.

But, I agree with Mythran that there's really no benefit it doing this.
It would be better to just create a new MemoryStream. I also agree
with him that calling the Dispose() method on the MemoryStream before
you discard it is better.

From a practical standpoint, the Dispose() method doesn't do much of
anything useful with a MemoryStream, but it's a "best practice" to
always dispose of objects that implement IDisposable by calling their
Dispose() method when you're done with the object.

Pete
 
J

Jeff Johnson

I was thinking in use stream.Flush(); but it says about Flush:
"overides flush so no action is performed"

The Flush() method is used with streams whose "ultimate destination" is not
memory (which is why the MemoryStream does nothing). Flush() just forces the
current "unwritten" contents of the stream out to the target medium, be it
the network wire, a file, or whatever.
 
S

shapper

Hello,

I created the following code:

Document _document = new Document {
Created = DateTime.UtcNow,
File = document.File,
Title = document.Title,
Updated = DateTime.UtcNow
};
_context.Documents.InsertOnSubmit(_document);

MemoryStream fileStream = new MemoryStream();
fileStream.Write(document.File, 0, document.File.Length);
PDFFile file = PDFFile.Open(fileStream);

// Define pages
for (Int32 i = 0; i < file.PageCount; i++) {

// Define image
Bitmap image = file.GetPageImage(i, 96);
MemoryStream imageStream = new MemoryStream();
image.Save(imageStream,
System.Drawing.Imaging.ImageFormat.Png);
Byte[] data = new Byte[imageStream.Length];
imageStream.Dispose();

// Define page
Entities.Page _page = new Entities.Page { File = data, Key =
Guid.NewGuid(), Number = i + 1 };
Entities.DocumentPage _documentPage= new Entities.DocumentPage
{ Document = _document, Page = _page };
_context.Pages.InsertOnSubmit(_page);
_context.DocumentPages.InsertOnSubmit(_documentPage);

}
fileStream.Dispose();
_context.SubmitChanges();

I am getting the images from the document PDF file.
Then I insert the document in the database as well as the created
pages.
And I relate pages and documents buy creating DocumentPages records in
the database.

The problem is that all the pages files inserted on the database are
empty:
0x0000000000000...

What am I doing wrong?

Thanks,
Miguel
 
P

Peter Duniho

shapper said:
[...]
The problem is that all the pages files inserted on the database are
empty:
0x0000000000000...

What am I doing wrong?

Well, for one...you never do anything with the data in the "imageStream"
stream. You probably should be copying the bytes from it (e.g. using
the ToArray() method), or perhaps even just use the underlying byte[]
from the MemoryStream directly (if you can deal with tracking the number
of valid bytes in the underlying buffer, versus the actual length of the
buffer which might be longer).

The other thing that looks at least a little suspicious is that you
don't reset the stream position of the "fileStream" stream before
passing it to the PDFFile class. If the PDFFile class doesn't
reposition the stream, then when it goes to (presumably) read from the
stream, it will find it has no more data in it, because writing to the
stream leaves the position at the end.

Of course, as always, without a concise-but-complete code example that
reliably demonstrates the problem, it's impossible to say for sure
what's wrong. But perhaps one or both of the above observations are
relevant.

Pete
 
S

shapper

shapper said:
[...]
The problem is that all the pages files inserted on the database are
empty:
0x0000000000000...
What am I doing wrong?

Well, for one...you never do anything with the data in the "imageStream"
stream.  You probably should be copying the bytes from it (e.g. using
the ToArray() method), or perhaps even just use the underlying byte[]
from the MemoryStream directly (if you can deal with tracking the number
of valid bytes in the underlying buffer, versus the actual length of the
buffer which might be longer).

The other thing that looks at least a little suspicious is that you
don't reset the stream position of the "fileStream" stream before
passing it to the PDFFile class.  If the PDFFile class doesn't
reposition the stream, then when it goes to (presumably) read from the
stream, it will find it has no more data in it, because writing to the
stream leaves the position at the end.

Of course, as always, without a concise-but-complete code example that
reliably demonstrates the problem, it's impossible to say for sure
what's wrong.  But perhaps one or both of the above observations are
relevant.

Pete

I was able to solve it as follows:

// Define pdf file
MemoryStream fileStream = new MemoryStream();
fileStream.Write(document.File, 0, document.File.Length);
fileStream.Position = 0;
PDFFile file = PDFFile.Open(fileStream);

// Define pages
for (Int32 i = 0; i < file.PageCount; i++) {

// Define image
Bitmap image = file.GetPageImage(i, 96);
MemoryStream imageStream = new MemoryStream();
image.Save(imageStream,
System.Drawing.Imaging.ImageFormat.Png);
imageStream.Seek(0, SeekOrigin.Begin);
Byte[] data = new Byte[imageStream.Length];
imageStream.Read(data, 0, (Int32)imageStream.Length);

// Define page
Entities.Page _page = new Entities.Page { File = data, Key =
Guid.NewGuid(), Number = i + 1 };
Entities.DocumentPage _documentPage= new Entities.DocumentPage
{ Document = _document, Page = _page };
_context.Pages.InsertOnSubmit(_page);
_context.DocumentPages.InsertOnSubmit(_documentPage);

imageStream.Dispose();
}
fileStream.Dispose();

The problem was here:

imageStream.Seek(0, SeekOrigin.Begin);
Byte[] data = new Byte[imageStream.Length];
imageStream.Read(data, 0, (Int32)imageStream.Length);

Thank You,
Miguel
 
P

Peter Duniho

shapper said:
[...]
The problem was here:

imageStream.Seek(0, SeekOrigin.Begin);
Byte[] data = new Byte[imageStream.Length];
imageStream.Read(data, 0, (Int32)imageStream.Length);

Note that those three lines can be replaced with this:

byte[] data = imageStream.ToArray();

Pete
 
M

Mythran

Peter Duniho said:
shapper said:
[...]
The problem was here:

imageStream.Seek(0, SeekOrigin.Begin);
Byte[] data = new Byte[imageStream.Length];
imageStream.Read(data, 0, (Int32)imageStream.Length);

Note that those three lines can be replaced with this:

byte[] data = imageStream.ToArray();

Pete

Also note that calling Dispose directly, without the Dispose method being
called within a finally block, does not guarantee that the Dispose method is
called. The Dispose method won't be called, for example, when an exception
is thrown before Dispose method is reached....this is why my example showed
the creation of the objects that implement IDisposable inside the USING
statement, before the start of the USING block. "using" guarantees that
Dispose will be called before leaving the "using" block.

HTH,
Mythran
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top