Saving a stream to a .wav file in VB.NET - vb.net

I've pulled a wave file from an online service I use and am now trying to save the returned stream. This is my code so far:
Using wavout = request.GetResponse.GetResponseStream
'error begins on next line
wavout.Seek(0, SeekOrigin.Begin)
Dim fs As FileStream = File.Create("output.wav")
Dim buf(65536) As Byte
Dim len As Integer = 0
While ((len = wavout.Read(buf, 0, 65536)) > 0)
fs.Write(buf, 0, len)
fs.Close()
End While
End Using
When I run the code it comes up with an exception saying 'this stream does not support seek operations'.
Can anyone see where I'm going wrong?

Some streams doesn’t support seeking. You can know it by a test such as “CanSeek”.
I’ve changed some lines in your code giving that as an answer to help you understanding the mechanism.
Dim request As Net.HttpWebRequest = CType(Net.WebRequest.Create("yoururlhere.com"), Net.HttpWebRequest)
Using wavout As IO.Stream = request.GetResponse().GetResponseStream()
'usnig this test you can avoid exceptions on seeking
If wavout.CanSeek Then
wavout.Seek(0, System.IO.SeekOrigin.Begin)
End If
Using fs As IO.FileStream = IO.File.Create("output.wav")
Dim buf(1024 * 8) As Byte
Dim len As Integer
Do
len = wavout.Read(buf, 0, buf.Length)
If len = 0 Then Exit Do
fs.Write(buf, 0, len)
Loop
End Using
End Using

Related

Direct Streaming Method CopyTo does not find the end

I am reading a SSE by using this method
Public Shared Sub ReadStreamForever(ByVal stream As Stream)
Dim encoder = New UTF8Encoding()
Dim buffer = New Byte(2047) {}
Dim counter As Integer = 0
While True
If stream.CanRead Then
Dim len As Integer = stream.Read(buffer, 0, 2048)
counter = counter + 1
If len > 0 Then
Dim text = encoder.GetString(buffer, 0, len)
SSEApplication.Push(text) 'Here I collect the text slices to a List(of string) object
Else
Exit While
End If
Else
Exit While
End If
End While
SSEApplication.writer() 'Here I write the content to a .txt file
End Sub
With my example data it takes about 2 seconds. I would prefer not to read the stream into memory though and tried this method
Public Shared Sub ReadStreamForever1(ByVal stream As Stream)
Dim output As FileStream = File.OpenWrite("C:\Users\mini_dataset.txt")
While True
If stream.CanRead Then
stream.CopyTo(output)
Else
Exit While
End If
End While
End Sub
But the process ends up in an endless loop (I guess) at least to me it looks like the end of the stream can not be found. I can break the process after a few seconds and all the data are in the .txt file. Any idea what I can do to get the direct stream to file method working?
Stream.CanRead tells you whether a stream supports reading. Since it's apparently readable, While True will go on forever.
Let's verify whether the output Stream.CanWrite instead.
Public Shared Sub ReadStreamForever1(ByVal stream As Stream)
Using output As FileStream = File.OpenWrite("[Output file path]")
If output.CanWrite Then
stream.CopyTo(output)
End If
End Using
End Sub
If the process takes some time and you need to report its progress, you could read the stream using a buffer (I didn't add any error checking but of course a try/catch block should be used):
(Here, with 100 parts division commonly used by a ProgressBar)
Public Sub ReadStreamForever1(ByVal stream As Stream)
Dim BufferLength As Integer = 81920 'As the default stream buffer
Dim Buffer(BufferLength) As Byte
Dim BytesRead As Long = 0L
Using output As FileStream = File.OpenWrite("[Output file path]")
If output.CanWrite Then
Dim Part As Long = stream.Length \ 100
Dim PartCount As Integer = 0
Dim read As Integer = 0
Do
read = stream.Read(Buffer, 0, BufferLength)
If read = 0 Then Exit Do
If (BytesRead / Part > PartCount) Then
PartCount += 1
'ReportWriteProgress(PartCount)
End If
output.Write(Buffer, 0, read)
BytesRead += read
Loop
End If
End Using
End Sub

twain ocr function returns empty byte

i have the below code:
ddlResultFormat.Items.Add("Text")
dynamicDotNetTwain1.LoadImage("C:\Users\elj\Desktop\3b072e9b-76b4-4776-bd3c-5984074d8ecd.png")
Dim r = dynamicDotNetTwain1.GetImage(dynamicDotNetTwain1.CurrentImageIndexInBuffer).Width.ToString()
Dim l = dynamicDotNetTwain1.GetImage(dynamicDotNetTwain1.CurrentImageIndexInBuffer).Height.ToString()
Dim languageFolder As String
languageFolder = "C:\Program Files (x86)\Dynamsoft\Dynamic .NET TWAIN 5.2 Trial\Samples\Bin\"
Dim languages As New Dictionary(Of String, String)
languages.Add("English", "eng")
Me.dynamicDotNetTwain1.OCRTessDataPath = languageFolder
Me.dynamicDotNetTwain1.OCRLanguage = "English"
Dim ocrResultFormat As Dynamsoft.DotNet.TWAIN.OCR.ResultFormat
ocrResultFormat = CType(System.Enum.Parse(GetType(Dynamsoft.DotNet.TWAIN.OCR.ResultFormat), Val("&H" & 0)), Dynamsoft.DotNet.TWAIN.OCR.ResultFormat)
Me.dynamicDotNetTwain1.OCRResultFormat = ResultFormat.Text
Dim strDllPath As String
strDllPath = "C:\Program Files (x86)\Dynamsoft\Dynamic .NET TWAIN 5.2 Trial\Redistributable\OCRResources\"
dynamicDotNetTwain1.OCRDllPath = strDllPath
If (Me.dynamicDotNetTwain1.CurrentImageIndexInBuffer < 0) Then
Dim jajajja = "Please load an image before doing OCR!"
End If
Dim sbytes As Byte()
sbytes = Me.dynamicDotNetTwain1.OCR(Me.dynamicDotNetTwain1.CurrentSelectedImageIndicesInBuffer)
the problem that i'm facing is that the sbytes byte array is being always set to empty although the indice in the buffer is correct and the paths and the dll are well implemented but the convert to the byte array is not being successful i'm not getting any exception but the length of the byte is 0
any idea how can i fix this?
Please update the following line of code and try again.
Me.dynamicDotNetTwain1.OCRLanguage = "eng" 'not English

Stream read return length 0 while stream is open and has valid data in it

I have a bit of a problem : in an winForm app in VS2010 win 7 compiling to x86, I try to do what Alvas.Audio seems to work. See (c# ex: http://alvas.net/alvas.audio,tips.aspx#tip94) for reference.
Dim data() As Byte = wr.ReadData(second * i, second)
The result give me data.length()=0. I do not have any exception, I can read format from it and whatever reader I use I got this problem.
EDIT : After some tests, it seems like the uncompressed file I create in the first step (in PCM format, with .wav extension) can not be recognized by the Alvas.audio library for the second step. I must miss something around Audio file markups or something alike.
Here is the code that might be the source (basically this is step 1):
Dim functOut As String = String.Empty
Dim wr As Alvas.Audio.IAudioReader = Nothing
Dim fs As IO.FileStream = Nothing
Dim i As Integer = 0
Dim tmpData() As Byte = Nothing
Dim dataPCM() As Byte = Nothing
Dim newFormat As IntPtr = IntPtr.Zero
Try
Select Case IO.Path.GetExtension(filename).ToLower()
Case ".wav"
wr = New Alvas.Audio.WaveReader(IO.File.OpenRead(filename))
filename = IO.Path.GetTempPath & IO.Path.GetFileNameWithoutExtension(filename) & "2" & IO.Path.GetExtension(filename)
Case ".mp3"
wr = New Alvas.Audio.Mp3Reader(IO.File.OpenRead(filename))
Case Else : wr = New Alvas.Audio.DsReader(filename)
End Select
functOut = IO.Path.ChangeExtension(filename, ".wav")
Dim format As IntPtr = wr.ReadFormat()
Dim formatDetail As Alvas.Audio.WaveFormat = Alvas.Audio.AudioCompressionManager.GetWaveFormat(format)
If formatDetail.wFormatTag = Alvas.Audio.AudioCompressionManager.MpegLayer3FormatTag Then
Alvas.Audio.AudioCompressionManager.Mp3ToWav(filename, functOut)
Return True
Else
IO.File.Create(functOut).Close()
While True
tmpData = wr.ReadData(SECONDS * i, SECONDS)
If tmpData Is Nothing Or tmpData.Length = 0 Then Exit While
If formatDetail.wBitsPerSample < 16 Then
Alvas.Audio.AudioCompressionManager.ToPcm16Bit(format, tmpData, newFormat, dataPCM)
Else
newFormat = format
dataPCM = tmpData
End If
formatDetail = Alvas.Audio.AudioCompressionManager.GetWaveFormat(newFormat)
fs = IO.File.Open(filename, IO.FileMode.Append, IO.FileAccess.Write)
Using ww As New Alvas.Audio.WaveWriter(fs, Alvas.Audio.AudioCompressionManager.FormatBytes(newFormat))
ww.Write(dataPCM, 0, dataPCM.Length())
End Using
i += 1
tmpData = Nothing
End While
Return True
End If
wr.Close()
Catch ex As Exception
filename = String.Empty
Throw ex
Finally
fs.Close()
wr.Close()
filename = functOut
GC.Collect()
End Try
How can I write the resulted stream to be sure I can read it again later?
Any ideas will be great appreciated.
I found a solution.
PCM files are headerless. So when saved, even with waveWriter and the line Alvas.Audio.AudioCompressionManager.FormatBytes(newFormat) was ignored.
Two things can be done:
find a reader that recognize headerless files and allows to read from it.
refactor code to decode into PCM file and encode it into the new format (e.g .mp3) without writing the resulted file into File system (much better)

start an executable application from resources without saving it somewhere

If i have a file ( appres.exe ) in the resources of my VB 2008 Application (myVbApp.exe), how can I start from there? I don't want to save it (appres.exe) somewhere else before start, i want only myVbApp.exe, no more files.
Retrieve the EXE from the resources:
Dim l as System.IO.Stream = Reflection.Assembly.GetEntryAssembly.GetManifestResourceStream(String.Format("{0}.{1}", "ApplicationProjectName", "YourExeName"))
Then save it to temp folder - example method:
Private Sub SaveStreamToFile(ByVal p_stream As Stream, ByVal p_fileName As String)
Dim l_streamWriter As System.IO.FileStream = System.IO.File.Create(p_fileName)
Try
Dim l_bytes(65536) As Byte
Dim l_offset As Integer = 0
Dim l_readBytes As Integer
Do
l_readBytes = p_stream.Read(l_bytes, 0, 65536)
l_streamWriter.Write(l_bytes, 0, l_readBytes)
l_offset += l_readBytes
Loop While (l_readBytes > 0)
Debug.WriteLine("Num Of bytes Read: " + l_offset.ToString)
Catch ex As Exception
'log error
Finally
p_stream.Close()
l_streamWriter.Close()
End Try
End Sub
Now that you got the EXE in a temp folder, you can regulary lunch it using:
Process.Start("EXE_PATH")
And delete it once the process is done.
You can try this :
Dim SetupPath As String = Application.StartupPath & "\appres.exe"
Using sCreateMSIFile As New FileStream(SetupPath, FileMode.Create)
sCreateMSIFile.Write(My.Resources.yourexefilename, 0, My.Resources.Yourexefilename.Length)
End Using
Process.Start(SetupPath)

Reading a file bug in VB.NET?

The way this file works is there is a null buffer, then a user check sum then a byte that gives you the user name letter count, then a byte for how many bytes to skip to the next user and a byte for which user file the user keeps their settings in.
the loop with the usersm variable in the IF statement sets up the whole file stream for extraction. However with almost the exact same code the else clause specifically the str.Read(xnl, 0, usn - 1) in the else code appears to be reading the very beginning of the file despite the position of the filestream being set earlier, anyone know whats happening here?
this is in vb2005
Private Sub readusersdata(ByVal userdatafile As String)
ListView1.BeginUpdate()
ListView1.Items.Clear()
Using snxl As IO.Stream = IO.File.Open(userdatafile, IO.FileMode.Open)
Using str As New IO.StreamReader(snxl)
str.BaseStream.Position = 4
Dim usersm As Integer = str.BaseStream.ReadByte()
Dim users As Integer = usersm
While users > 0
If usersm = users Then
Dim trailtouser As Integer = 0
str.BaseStream.Position = 6
Dim ust As Integer = str.BaseStream.ReadByte()
str.BaseStream.Position = 8
Dim snb(ust - 1) As Char
str.ReadBlock(snb, 0, ust)
Dim bst = New String(snb)
If usersm = 1 Then
str.BaseStream.Position = 16
Else
str.BaseStream.Position = 15
End If
cLVN(ListView1, bst, str.BaseStream.ReadByte)
str.BaseStream.Position = 8 + snb.Length
str.BaseStream.Position += str.BaseStream.ReadByte + 1
Else
Dim usn As Integer = str.BaseStream.ReadByte
str.BaseStream.Position += 2
Dim chrpos As Integer = str.BaseStream.Position
Dim xnl(usn - 1) As Char
str.Read(xnl, 0, usn - 1)
Dim skpbyte As Integer = str.BaseStream.ReadByte
str.BaseStream.Position += 3
Dim udata As Integer = str.BaseStream.ReadByte
End If
users -= 1
End While
End Using
End Using
ListView1.EndUpdate()
End Sub
When you change the position of the underlying stream, the StreamReader doesn't know you've done that. If it's previously read "too much" data (deliberately, for the sake of efficiency - it tries to avoid doing lots of little reads on the underlying stream) then it will have buffered data that it'll use instead of talking directly to the repositioned stream. You need to call StreamReader.DiscardBufferedData after repositioning the stream to avoid that.