Read data from networkstream into array - vb.net

Is there a better way of reading data from a networkstream into an array. The following code works, but it takes a while to receive large amounts of data:
Private Function ReadBytes(ByVal NetworkStream As System.Net.Sockets.NetworkStream) As Byte()
Dim Bytes As Byte() = {}
Dim Index As Integer = 0
While NetworkStream.DataAvailable = True
Array.Resize(Bytes, Index + 1)
Bytes(Index) = NetworkStream.ReadByte()
Index += 1
End While
Return Bytes
End Function
Thanks for any help in advance.

Looking through the docs, this is what I came up with (not tested):
Private Sub ReadBytes(ByRef Bytes() As Byte, ByRef NetworkStream As System.Net.Sockets.NetworkStream)
Dim nBr, u As Integer ' nBr = nr. of bytes read
u = -1
Dim L% = 1024 'increase this number to get better performance
While NetworkStream.DataAvailable
ReDim Preserve Bytes(u + L)
nBr = NetworkStream.Read(Bytes, u + 1, L)
u += nBr
If nBr < L Then ReDim Preserve Bytes(u)
End While
End Sub
Note: Pass large arrays ByRef instead of Function result to avoid unnecessary copying of memory.

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

Finding HEX value at a specific offset in VB.net

I'm trying to figure out how to read a section of bytes (Say 16) starting at a specific address, say 0x2050. I'd like to get the 16 bits output in hex values into a label.
I've been trying to figure out BinaryReader, and FileStreams but I'm not entirely sure what the difference is, or which one I should be using.
*I've seen a lot of threads mentioning file size could be an issue, and I'd like to point out that some files I'll be checking may be up to 4gb in size.
I've tried the following:
Dim bytes() As Byte = New Byte(OpenedFile.Length) {}
ListBox1.Items.Add(Conversion.Hex(OpenedFile.Read(bytes, &H2050, 6)))
But this simply writes 6 bytes to the file, and I'm not sure why. There is no output in the listbox.
How about something like the following?:
Sub Main()
Dim pos As Long = 8272
Dim requiredBytes As Integer = 2
Dim value(0 To requiredBytes - 1) As Byte
Using reader As New BinaryReader(File.Open("File.bin", FileMode.Open))
' Loop through length of file.
Dim fileLength As Long = reader.BaseStream.Length
Dim byteCount As Integer = 0
reader.BaseStream.Seek(pos, SeekOrigin.Begin)
While pos < fileLength And byteCount < requiredBytes
value(byteCount) = reader.ReadByte()
pos += 1
byteCount += 1
End While
End Using
Dim displayValue As String
displayValue = BitConverter.ToString(value)
End Sub

example for VB.NET to calculate CRC16 of an string or Byte Array

With reference to this link
Calculate CRC32 of an String or Byte Array
I modified the code in order to calculate the CRC16 instead of CRC32, however I am getting wrong result, can some one point me where is the mistake?
Private Sub Main()
Crc16.ComputeChecksum(Encoding.UTF8.GetBytes("Some string"))
End Sub
Public Class CRC16
Shared table As UShort()
Shared Sub New()
Dim poly As UShort = &HA001US 'calculates CRC-16 using A001 polynomial (modbus)
table = New UShort(255) {}
Dim temp As UShort = 0
For i As UShort = 0 To table.Length - 1
temp = i
For j As Integer = 8 To 1 Step -1
If (temp And 1) = 1 Then
temp = CUShort((temp >> 1) Xor poly)
Else
temp >>= 1
End If
Next
table(i) = temp
Next
End Sub
Public Shared Function ComputeChecksum(ByVal bytes As Byte()) As UShort
Dim crc As UShort = &H0US ' The calculation start with 0x00
For i As Integer = 0 To bytes.Length - 1
Dim index As Byte = CByte(((crc) And &HFF) Xor bytes(i))
crc = CUShort((crc >> 8) Xor table(index))
Next
Return Not crc
End Function
End Class
Try this, it's working VB6 code for Instrument control. (sCommand is a temp string which contains all Bytes, Result is added to sCommand, Modbus is using LSB first, TextToString and StringToAscii are functions to convert a readable string "FF EE" into ASCII and back, thus they are not of interest here.):
Private Sub cmdCRC16_Click()
Dim sCommand As String
Dim x As Long
Dim y As Long
Dim lCRC As Long
sCommand = TextToString(txtASCII)
'Initial value
lCRC = 65535 '(&HFFFF results in Integer -1)
For x = 1 To Len(sCommand)
lCRC = lCRC Xor Asc(Mid(sCommand, x, 1))
For y = 1 To 8
If (lCRC Mod 2) > 0 Then
lCRC = (lCRC And 65534) / 2
lCRC = lCRC Xor 40961 '(&HA001 results in whatever negative integer)
Else
lCRC = (lCRC And 65534) / 2
End If
Next y
Next x
'Add CRC with LSB first
sCommand = sCommand + Chr(lCRC And 255)
sCommand = sCommand + Chr((lCRC And 65280) / 256)
txtASCII = StringToASCII(sCommand)
End Sub
I just came accross the same issue. Simple solution is to omit negation at the end, so just change your "Return Not crc" to "Return crc" and you be fine.
There are various variants of CRC-16, where "CRC-16" normally refers to the IBM variant, also called "ARC". It uses an XorOut value of zero. See Catalogue of parametrised CRC algorithms with 16 bits.

cant understand this function

Public Function encrypt(ByVal message As Byte(), ByVal password As String) As Byte()
Dim passarr As Byte() = System.Text.Encoding.Default.GetBytes(password)
Randomize()
Dim rand As Integer = Int((255 - 0 + 1) * Rnd()) + 1
Dim outarr(message.Length) As Byte
Dim u As Integer
For i As Integer = 0 To message.Length - 1
outarr(i) += (message(i) Xor passarr(u)) Xor rand
If u = password.Length - 1 Then u = 0 Else u = u + 1
Next
outarr(message.Length) = 112 Xor rand
Return outarr
End Function
Questions I want to ask:
getbytes(password) its already declared as string ...why would you want to get bytes!!
what is the role of message here?
what are rand and outarr doing to message?
outarr(message.Length) = 112 Xor rand - I cannot understand this
The function is encrypting a string. Since it is performing arithmetic calculations on the message, you need a byte represenation (so you can do the arithmetics on the bytes).
outarr is the array of bytes that is the result of the encryption. The encryption is based on a random value rand, which is an integer between 0 and 255.
The 112 xor rand part, I believe, is there to be able to get the random number back from the encrypted code (by knowing the "secret" value 112)

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.