I have a resource in named StoreCode, I can't seem to read the file using:
Dim readBinaryFile As BinaryReader
readBinaryFile = New BinaryReader(My.Resources.StoreCode)
There is an error:
Value of type:'1-dimensional array of Byte' cannot be converted to 'System.IO.Stream'
How do I correctly read the Binary File?
Seems My.Resources.StoreCode is a byte[] for that reason you need to copy it to a MemoryStream object and then use a BinaryReader to read the stream's content.
Using ms As New MemoryStream(My.Resources.StoreCode)
Using readBinaryFile As New BinaryReader(ms)
'read operations
End Using
End Using
I hope it helps.
My.Resources.StoreCode is probably a an array of bytes. Instead, it needs to be a file stream, similar to this:
Dim readBinaryFile As BinaryReader
Dim fs As System.IO.Stream = File.Open(pathstring, FileMode.Open)
readBinaryFile = New BinaryReader(fs)
Related
I have a CSV file in my project resources which I want to read using FileIO.TextFieldParser
I tried Dim parser = new TextFieldParser(My.Resources.ArticlesCSV), but since TextFieldParser expects either a path (as string) or a stream, this is not working.
I guess one possibility is to convert the resource to a stream, but I cannot find how to do that...
What is the best way to get this working?
You can create a new instance of IO.StringReader which is of type TextReader that TextFieldParser will accept. Just pass your CSV file (Thanks to AndrewMorton)
Using strReader As New IO.StringReader(My.Resources.ArticlesCSV)
Using textparser As New TextFieldParser(strReader)
textparser.Delimiters = {","}
While Not textparser.EndOfData
Dim curRow = textparser.ReadFields()
' Do stuff
End While
End Using
End Using
Dealing with some legacy code that parses .TIF images (front and back images for checks) from an .IMG file. For example, I have the following file: 05090001.IMG and then I have the following values about that file:
FrontStart: 8 | FrontLength: 10600 | RearStart: 10608 | RearLength: 6372
The size of 05090001.IMG is 16980 bytes, so it seems that the front image should be 10600 bytes and does in fact create a valid .TIF file while the rear image always ends up corrupt.
This is the existing code that retrieves the front .TIF file:
Dim fs As New FileStream(Me.FileName, FileMode.Open, FileAccess.Read)
Dim sr As New BinaryReader(fs)
Dim fname As String = {long formula to generate fname}
Dim fsFront As New FileStream(fname & "_Front.tif", FileMode.Create)
Dim swFront As New BinaryWriter(fsFront)
Dim imgBytesFront As Byte()
fs = New FileStream(Path.Combine(DownImageFiles, dr("ImgFile")), FileMode.Open, FileAccess.Read)
sr = New BinaryReader(fs)
imgBytesFront = sr.ReadBytes(dr("FrontLength"))
swFront.Write(imgBytesFront)
swFront.Close()
fsFront.Close()
I'm trying to add similar code to access the rear image file:
Dim fsRear As New FileStream(fname & "_Rear.tif", FileMode.Create)
Dim swRear As New BinaryWriter(fsRear)
Dim imgBytesRear As Byte()
fs = New FileStream(Path.Combine(DownImageFiles, dr("ImgFile")), FileMode.Open, FileAccess.Read)
Using br As New BinaryReader(fs)
br.BaseStream.Seek(Long.Parse(dr("FrontLength"), Globalization.NumberStyles.Integer), SeekOrigin.Begin)
imgBytesRear = br.ReadBytes(dr("RearLength"))
End Using
imgBytesRear = sr.ReadBytes(dr("RearLength"))
swRear.Write(imgBytesRear)
swRear.Close()
fsRear.Close()
This generates an image, but Windows says it is "damaged, corrupted, or is too large".
Any ideas what I'm missing? Am I using the Seek method properly? Am I somehow reading the first 6372 bytes again instead of skipping the first 10600 and starting there? Any help greatly appreciated!
Thanks to several people in the comments above, I found that simply loading the .IMG file in as a System.Drawing.Image, I could then split it into individual page files.
Dim tiffCheck As Image = Image.FromFile(Path.Combine(DownImageFiles, dr("ImgFile")))
After that, I essentially followed the solution under the Split() function here:
https://code.msdn.microsoft.com/windowsdesktop/Split-multi-page-tiff-file-058050cc
I'm creating a file on the fly on a WebAPI call, and sending that file back to the client.
I think I'm misunderstanding flush/close on a FileStream:
Dim path As String = tempFolder & "\" & fileName
Dim result As New HttpResponseMessage(HttpStatusCode.OK)
Dim stream As New FileStream(path, FileMode.Open)
With result
.Content = New StreamContent(stream)
.Content.Headers.ContentDisposition = New Headers.ContentDispositionHeaderValue("attachment")
.Content.Headers.ContentDisposition.FileName = fileName
.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("application/octet-stream")
.Content.Headers.ContentLength = stream.Length
End With
'stream.Flush()
'stream.Close()
'Directory.Delete(tempFolder, True)
Return result
You can see where I've commented things out above.
Questions:
Does the stream flush/close itself?
How can I delete the tempFolder after returning the result?
On top of all this, it would be great to know how to generate the file and send it to the user without writing it to the file system first. I'm confident this is possible, but I'm not sure how. I'd love to be able to understand how to do this, and solve my current problem.
Update:
I went ahead with accepted answer, and found it to be quite simple:
Dim ReturnStream As MemoryStream = New MemoryStream()
Dim WriteStream As StreamWriter = New StreamWriter(ReturnStream)
With WriteStream
.WriteLine("...")
End With
WriteStream.Flush()
WriteStream.Close()
Dim byteArray As Byte() = ReturnStream.ToArray()
ReturnStream.Flush()
ReturnStream.Close()
Then I was able to stream the content as bytearraycontent:
With result
.Content = New ByteArrayContent(byteArray)
...
End With
On top of all this, it would be great to know how to generate the file and send it to the user without writing it to the file system first. I'm confident this is possible, but I'm not sure how. I'd love to be able to understand how to do this, and solve my current problem.
To do the same thing without writing a file to disk, you might look into the MemoryStream class. As you'd guess, it streams data from memory like the FileStream does from a file. The two main steps would be:
Take your object in memory and instead of writing it to a file, you'd serialize it into a MemoryStream using a BinaryFormatter or other method (see that topic on another StackOverflow Q here: How to convert an object to a byte array in C#).
Pass the MemoryStream to the StreamContent method, exactly the same way you're passing the FileStream now.
I have some code that used a FileStream, StreamWriter and XmlDocument to produce Excel-compatible output files. Very useful!
However I now have a need to make copies of the file, and I'd like to do that in-memory. So I took my original FileStream code and changed the FileStream to a MemoryStream, and then wrapped that in this function:
'----------------------------------------------------------------------------------
Friend Sub Save(Optional ByVal SaveCalculatedResults As Boolean = True)
Dim MStream As MemoryStream
Dim FStream As FileStream
Dim Bytes As Byte()
'make the stream containing the XML
MStream = ToXLSL(SaveCalculatedResults)
If MStream.Length = 0 Then Return
'then read that data into a byte buffer
ReDim Bytes(CInt(MStream.Length))
MStream.Read(Bytes, 0, CInt(MStream.Length))
'and then write it to "us"
FStream = New FileStream("C:\OUTFILE.XLSX", FileMode.Create)
FStream.Write(Bytes, 0, CInt(MStream.Length))
FStream.Flush()
End Sub
This creates a file in the correct location, it has the exact same length as it did before, but opening it in Excel causes an error about the file format being invalid.
Can anyone see any obvious problems in that code? Perhaps I am writing the bytes backwards? Is this possibly a text encoding problem? 32/64 problem?
p.s. I tried using CopyTo, but that doesn't seem to work in VB?
It requires guessing what ToXLSL() does but the behavior gives a strong hint: the MemoryStream's Position is located at the end of the stream. So the Read() call doesn't actually read anything. Verify by checking its return value.
Just get rid of Bytes() entirely, it is very wasteful to duplicate the data like this. You don't need it, the MemoryStream already gives you access to the data:
Using FStream = New FileStream("C:\OUTFILE.XLSX", FileMode.Create)
FStream.Write(MStream.GetBuffer(), 0, CInt(MStream.Length))
End Using
Do note that the Using statement is not optional. And that you cannot write to C:\
I have a web service that takes the content of a canvas tag and saves it into a MongoDB GridFS store.
The code below works, however it requires saving the image to disk before sending it to MongoDB.
Using postBody As Stream = Request.InputStream
' Get the body of the HTTP POST (the data:image/png)
postBody.Seek(0, SeekOrigin.Begin)
Dim imageData As String = New StreamReader(postBody).ReadToEnd
Dim base64Data = Regex.Match(imageData, "data:image/(?<type>.+?),(?<data>.+)").Groups("data").Value
Dim data As Byte() = Convert.FromBase64String(base64Data)
Using stream = New MemoryStream(data, 0, data.Length)
Dim img As System.Drawing.Image = System.Drawing.Image.FromStream(stream)
Dim directory = Server.MapPath("~/App_Data/temp/")
Dim file = String.Concat(directory, id, ".png")
img.Save(file, System.Drawing.Imaging.ImageFormat.Png)
Using fs = New FileStream(file, FileMode.Open)
db.GridFS.Upload(fs, id & ".png")
End Using
End Using
End Using
Is there a better way, perhaps without the need to persist it to disk before uploading to MongoDB?
As suggested in the comments, just use the Stream as an argument to Upload instead of writing out to file.
And also note that you do not have to convert to base64 in order to send the file via GridFS (or a plain mongo field for that matter). The input can be binary, unless of course you always want your data base64 encoded for your convenience.