How to correctly read a random access file in VB.NET - vb.net

I am attempting to read a random access file, but I am getting the following error on the first file Error 5 (unable to read beyond end of the stream). I am not sure what I am doing wrong here, how might I fix this issue?
Structure StdSections
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(15), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=15)> Public A() As Char 'BEAM --- complete beam designation 15
'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
<VBFixedString(2), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst:=2)> Public B() As Char 'DSG --- shape ie "W" or "C" 2
Dim C As Single 'DN --- nominal depth of section 4
Dim d As Single 'WGT --- weight 4
.
.
.
End structure
''Note 'File1'is the existing RAF and holds complete path!
Dim i,ffr,fLength,lastmembNo as integer
sectionFound = False
Dim std As new StdSections
fLength = Len(std)
If fLength = 0 Then fLength = 168 ' 177
ffr = FreeFile()
FileOpen(ffr, File1, OpenMode.Random, OpenAccess.Read, OpenShare.LockRead, fLength)
lastmembNo = CInt(LOF(ffr)) \ fLength
For i = 1 To lastmembNo
FileGet(ffr, std, i)
>>Error 5 (unable to read beyond end of the stream) <<<
If Trim(memberID) = Trim(std.A) Then
sectionFound = True
end if
next i

Wow Freefile! That's a blast from the past!
I haven't really used the old OpenFile etc. file access methods in VB.NET, so I'm just speculating, but in .NET many of the variable types got changed in size. e.g. an Integer is now 32-bits (4 bytes), I think a Boolean is different, though a Single is still 4 bytes.
Also, strings in .NET are by default in Unicode, not ASCII, so you cannot rely on 1 character=1 byte in a .NET String variable. In fact, .NET actualy "JIT compiles" programs on the PC before running, so you can't really lay out structures in memory easily like the old days.
If you want to switch to the new "Stream" based objects, here's some code to get you started:
Dim strFilename As String = "C:\Junk\Junk.txt"
Dim strTest As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Call My.Computer.FileSystem.WriteAllText(strFilename, strTest, False)
Dim byt(2) As Byte
Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
fs.Seek(16, SeekOrigin.Begin)
fs.Read(byt, 0, 3)
Dim s As String = Chr(byt(0)) & Chr(byt(1)) & Chr(byt(2))
MsgBox(s)
fs.Seek(5, SeekOrigin.Begin)
fs.Write(byt, 0, 3)
End Using
Dim strModded As String = My.Computer.FileSystem.ReadAllText(strFilename)
MsgBox(strModded)
I wouldn't blame you for keeping the old method though: with the new method, you'll need to define a class, and then have a custom routine to convert from Byte() to the properties of the class. More work than simply loading bytes from the file into memory.

OK, I think you should switch to the ".NET way", as follows:
Imports System.IO
Imports System.Xml
Public Class Form1
Public Const gintRecLen_CONST As Integer = 177
Class StdSections2
Private mstrA As String
Public Property A() As String
Get
Return mstrA
End Get
Set(ByVal value As String)
If value.Length <> 15 Then
Throw New Exception("Wrong size")
End If
mstrA = value
End Set
End Property
Private mstrB As String
Public Property B() As String
Get
Return mstrB
End Get
Set(ByVal value As String)
If value.Length <> 2 Then
Throw New Exception("Wrong size")
End If
mstrB = value
End Set
End Property
Public C(39) As Single
Public Shared Function FromBytes(byt() As Byte) As StdSections2
Dim output As New StdSections2
If byt.Length <> gintRecLen_CONST Then
Throw New Exception("Wrong size")
End If
For i As Integer = 0 To 14
output.mstrA &= Chr(byt(i))
Next i
For i As Integer = 15 To 16
output.mstrB &= Chr(byt(i))
Next i
For i As Integer = 0 To 39
Dim bytTemp(3) As Byte
output.C(i) = BitConverter.ToSingle(byt, 17 + 4 * i)
Next i
Return output
End Function
End Class
Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim strFilename As String = "C:\Junk\Junk.txt"
Dim strMemberID As String = "foo"
Dim intRecCount As Integer = CInt(My.Computer.FileSystem.GetFileInfo(strFilename).Length) \ gintRecLen_CONST
Dim blnSectionFound As Boolean = False
Using fs As New FileStream(strFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
For intRec As Integer = 0 To intRecCount - 1
Dim intRecPos As Integer = gintRecLen_CONST * intRec
fs.Seek(intRecPos, SeekOrigin.Begin)
Dim byt(gintRecLen_CONST - 1) As Byte
fs.Read(byt, 0, gintRecLen_CONST)
Dim ss2 As StdSections2 = StdSections2.FromBytes(byt)
'MsgBox(ss2.A & ":" & ss2.C(3)) 'debugging
If strMemberID.Trim = ss2.A.Trim Then
blnSectionFound = True
Exit For
End If
Next intRec
End Using
MsgBox(blnSectionFound.ToString)
End Sub
End Class
We define a class called StdSections2 which uses .NET strings and an array of Singles. We use 0-based arrays everywhere. We load the file using the new FileStream object, and use the Seek() command to find the position we want. We then load raw bytes out of the file, and use Chr() and BitConverter.ToSingle() to convert the raw bytes into strings and singles.

I'm not sure about your example but this one however, works:
Public Class Form1
Const maxLenName = 30
Structure person
<VBFixedString(maxLenName)> Dim name As String
Dim age As Byte
End Structure
Private Sub Form1_Load(sender As [Object], e As EventArgs) Handles MyBase.Load
Dim entryIn As New person
Dim recordLen As Integer = Len(entryIn)
Dim entry As person
If FileIO.FileSystem.FileExists("test.raf") Then Kill("test.raf")
FileOpen(1, "test.raf", OpenMode.Random,,, recordLen)
'write
entry.name = LSet("Bill", maxLenName)
entry.age = 25
FilePut(1, entry, 6) 'write to 6th record
'read
Dim nRecords As Integer = LOF(1) \ recordLen
FileGet(1, entryIn, nRecords)
FileClose(1)
Dim personName As String = RTrim(entryIn.name)
Dim personAge As Byte = entryIn.age
MsgBox(personName & "'s age is " & personAge)
End Sub
End Class

Related

New to programming language, need help to read a .dat file into array Vs VB, console .net framework

I am trying to read from a data file called TXT.dat and store the circled values into a separate array's using the type of commands I have used. I cannot use streamreader,streamwriter this is what I am learning at university but we were taught to read an array not certain values as I will be tested using a file which has
2 factorial values from a single file and store int two arrays.
I have spent hours trying before going to paid sites who always answer with i/o streamreader which doesnt help
.dat file i created to practice
MY CODE
Sub Main()
Const i_val As Integer = 6
Dim j As Integer = 6 'loop readers
Dim Arayn_Fact(i_val - 1) As Double 'array for 2nd value per line
Dim Aray_Fact2n(j - 1) As Double 'array for 4th value per line
Read_Values(i_val - 1, Arayn_Fact)
End Sub
Sub Read_Values(ByVal i As Integer, ByRef _A() As Double)
Dim fid1 As Integer = FreeFile()
Dim fid2 As Integer = FreeFile() + 1
Dim tmp As Double
FileOpen(fid1, "TXT.dat", OpenMode.Input, OpenAccess.Read)
For i = 0 To 5 Step 1
Input(fid1, tmp)
Input(fid1, _A(i))
Next i
FileClose(fid1)
Console.ReadKey()
End Sub
Without getting too fancy, here's some very basic code to do what you've outlined:
Sub Main()
Dim fileName As String = "txt.dat"
Dim Aray_Fact2() As Integer 'array for 2nd value per line
Dim Aray_Fact4() As Integer 'array for 4th value per line
Dim list2 As New List(Of Integer)
Dim list4 As New List(Of Integer)
Dim lines() As String = System.IO.File.ReadAllLines(fileName)
For Each line As String In lines
Dim values() As String = line.Split(",")
If values.Length >= 3 Then
Dim f2, f4 As Integer
If Integer.TryParse(values(1), f2) AndAlso Integer.TryParse(values(3), f4) Then
list2.Add(f2)
list4.Add(f4)
Else
Console.WriteLine("Invalid value in line: " & line)
End If
Else
Console.WriteLine("Invalid number of entries in line: " & line)
End If
Next
Aray_Fact2 = list2.ToArray
Aray_Fact4 = list4.ToArray
Console.WriteLine("Aray_Fact2: " & String.Join(",", Aray_Fact2))
Console.WriteLine("Aray_Fact4: " & String.Join(",", Aray_Fact4))
Console.Write("Press Enter to Quit...")
Console.ReadLine()
End Sub
If you are completely against the use of Lists and ToArray, then you'd have to read the file TWICE. Once to determine how many lines are in the file so you can dimension the arrays to the correct size. Then another time to actually read the values and populate the arrays.
First, some style things. Passing the array ByRef is incorrect. Arrays are already reference types, and so passing ByVal still passes the reference to the array object. But don't even pass the array in the first place. It's better practice to let the Read_Values() method create and return the array to the calling function.
And no one uses that ancient/ganky FileOpen() API anymore. I mean that. NO. ONE. It's not even appropriate for teaching, as the Stream types are closer to what the low level operating system/file system are doing. If you can't use StreamReader and friends, there are still better options out there.
Sub Main()
Dim Array_Fact() As Double = Read_Values("TXT.dat", 1)
Dim Array_Fact2n() As Double = Read_Values("TXT.dat", 3)
Console.ReadKey(True)
End Sub
Function Read_Values(filePath As String, position As Integer) As Double()
Dim lines() As String = File.ReadAllLines(filePath) 'Look Ma, no StreamReader
Dim result(lines.Length - 1) As Double
For i As Integer = 0 To Lines.Length - 1
result(i) = Double.Parse(lines(i).Split(",")(position).Trim())
Next line
Return result
End Function
But what I'd really do is keep the 2nd and 4th values in the same collection and read everything in one pass through the file. This uses features like Generics, Tuples, Lambdas+Linq, and more that you won't get to for some time, but I feel like it's useful to show you where you're going:
Sub Main()
Dim Facts = Read_Values("TXT.dat")
Console.WriteLine(String.Join(",",Facts.Select(Function(f) $"({f.Item1}:{f.Item2})")))
Console.ReadKey(True)
End Sub
Function Read_Values(filePath As String) As IEnumerable(Of (Double, Double))
Return File.ReadLines(filePath).Select(
Function(line) 'Poor man's CSV. In real code, I'd pull in a CSV parser from NuGet
Dim fields = line.Split(",")
Return (Double.Parse(fields(1).Trim()), Double.Parse(fields(3).Trim()))
End Function
)
End Function

Split a string array problems vb.net

I am new to VB.NET and would like to split a string into an array.
I have a string like:
613,710,200,127,127,'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
I want to split this into a array at ",".
I tried:
Dim variable() As String
Dim stext As String
stext = "mystringhere"
variable = Split(stext, ",")
My problem is the part of
'{\"js\":{\"\":\"16\",\"43451\":\"16\",\"65815\":\"16\",\"43452\":\"16\",\"41147\":\"16\",\"43449\":\"16\",\"43467\":\"16\",\"1249\":\"16\",\"43462\":\"16\",\"43468\":\"48\",\"43438\":\"64\",\"43439\":\"80\"}}',
is split too. I want this to get all together in variable(5). Is this posible?
thank you for help
What you need is a CSV parser in which you can set the field quote character. Unfortunately the TexFieldParser which comes with VB.NET doesn't have that facility. Fortunately, other ones do - here I have used the LumenWorksCsvReader, which is available as a NuGet package *.
Option Strict On
Option Infer On
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Module Module1
Sub Main()
Dim s = "613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL"
Using sr As New StringReader(s)
Using csvReader = New CsvReader(sr, delimiter:=","c, quote:="'"c, escape:="\"c, hasHeaders:=False)
Dim nFields = csvReader.FieldCount
While csvReader.ReadNextRecord()
For i = 0 To nFields - 1
Console.WriteLine(csvReader(i))
Next
End While
End Using
End Using
Console.ReadLine()
End Sub
End Module
which outputs
613
710
200
127
127
{"js":{"":"16","43451":"16","65815":"16","43452":"16","41147":"16","43449":"16","43467":"16","1249":"16","43462":"16","43468":"48","43438":"64","43439":"80"}}
rca
95
2048000
3
1
AABBCCDDEEFFGGHHIIJJKKLL=
xx.xx.xx.xx
NULL
Note that the double-quotes are doubled up in the literal string as that is the way to enter a single double-quote in VB.
If you really want the backslashes to remain, remove the escape:="\"c parameter.
If you are reading from a file then use the appropriate StreamReader instead of the StringReader.
Using the above, perhaps you have a Windows Forms program where you wanted to populate a RichTextBox with the data from, say, a text file named "C:\temp\CsvFile.txt" with the content
613,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','rca',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','xx.xx.xx.xx',NULL
614,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','din',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','yy.yy.yy.yy',NULL
615,710,200,127,127,'{\""js\"":{\""\"":\""16\"",\""43451\"":\""16\"",\""65815\"":\""16\"",\""43452\"":\""16\"",\""41147\"":\""16\"",\""43449\"":\""16\"",\""43467\"":\""16\"",\""1249\"":\""16\"",\""43462\"":\""16\"",\""43468\"":\""48\"",\""43438\"":\""64\"",\""43439\"":\""80\""}}','jst',95,2048000,3,1,'AABBCCDDEEFFGGHHIIJJKKLL=','zz.zz.zz.zz',NULL
you could use the above to come up with
Imports System.IO
Imports LumenWorks.Framework.IO.Csv
Public Class Form1
Public Class Datum
Property A As Integer
Property B As Integer
Property C As Integer
Property D As Integer
Property E As Integer
Property JsonData As String
Property SocketType As String
Property F As Integer
Property G As Integer
Property H As Integer
Property I As Integer
Property Base64Data As String
Property IpAddy As String
Property J As String
Public Overrides Function ToString() As String
Return $"{A}, {SocketType}, {IpAddy}, {B} ,{C}, {D}, {E}, {F}, {G}, {H}, {I}, {JsonData}, {Base64Data}, {J}"
End Function
End Class
Public Function GetData(filename As String) As List(Of Datum)
Dim data As New List(Of Datum)
Using sr As New StreamReader(filename)
Using csvReader = New CsvReader(sr, hasHeaders:=False, delimiter:=","c, quote:="'"c, escape:="\"c, comment:=Nothing, trimmingOptions:=ValueTrimmingOptions.UnquotedOnly)
Dim nFields = csvReader.FieldCount
If nFields <> 14 Then
Throw New MalformedCsvException("Did not find 14 fields in the file " & filename)
End If
While csvReader.ReadNextRecord()
Dim d As New Datum()
d.A = Integer.Parse(csvReader(0))
d.B = Integer.Parse(csvReader(1))
d.C = Integer.Parse(csvReader(2))
d.D = Integer.Parse(csvReader(3))
d.E = Integer.Parse(csvReader(4))
d.JsonData = csvReader(5)
d.SocketType = csvReader(6)
d.F = Integer.Parse(csvReader(7))
d.G = Integer.Parse(csvReader(8))
d.H = Integer.Parse(csvReader(9))
d.I = Integer.Parse(csvReader(10))
d.Base64Data = csvReader(11)
d.IpAddy = csvReader(12)
d.J = csvReader(13)
data.Add(d)
End While
End Using
End Using
Return data
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim srcFile = "C:\temp\CsvData.txt"
Dim dat = GetData(srcFile)
For Each d In dat
RichTextBox1.AppendText(d.ToString() & vbCrLf)
Next
End Sub
End Class
It might be necessary to perform more checks on the data when trying to parse it. Note that I made a function for the .ToString() method of the Datum class and put the properties in a different order just to demonstrate its use.
* Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution... Choose the "Browse" tab -> type in LumenWorksCsvReader -> select the one by Sébastien Lorion et al., -> tick your project name in the pane to the right -> click Install.
I am new to VB.NET and would like to split a string into an array.
...
variable = Split(stext,",")
Instead of
variable = Split(stext,",")
use
variable = stext.split(",")
If you want to get a bit more complicated on your split you would create an array of char data as such
dim data(3) as char
data(0) = ","c
data(1) = vbcrlf
data(2) = chr(34)
data(3) = vbtab
... and so on
variable = stext.split(data)

VB.NET writing comments to jpeg file programmatically

I searched stackoverflow and I realized that GetPropertyItem and SetPropertyItem can edit comments in JPEG file
Dim images As Image = System.Drawing.Image.FromFile("C:\\Sample.jpeg")
Dim MSGF As New ArrayList
Dim ID() As String = {"hello ","i am here"}
Dim propItem As PropertyItem = images.GetPropertyItem(40092)
Dim encoderParameters As New EncoderParameters(1)
encoderParameters.Param(0) = New EncoderParameter(Encoder.Quality, 100L)
For i = 0 To ID.Length - 1
Dim TEMP As String = ID(i)
For II = 0 To TEMP.Length - 1
MSGF.Add(Convert.ToInt32(TEMP(II)))
Next
Next
For i = 0 To MSGF.Count - 1
propItem.Value.SetValue(Convert.ToByte(MSGF(i)), i)
Next
images.SetPropertyItem(propItem)
images.Save(TextBox1.Text & "\" & "1" & TextBox2.Text)
What I realized was I can get comments from jpeg file by GetPropertyItem. However, comments is based on the ascii code. Therefore, I was trying to convert comment that I wanted to insert to ascii code.
propItem.Value.SetValue(Convert.ToByte(MSGF(i)), i)
This part was actually changed comments which already existed in the jpeg file.
However, if there is no comments in jpeg file, propItem.value.setValue doesn't work because there is nothing to edit.
Is there anyway to just add comments to jpeg file?
Based on this answer in C#, it could be as simple as this:
Dim jpeg = New JpegMetadataAdapter(pathToJpeg)
jpeg.Metadata.Comment = "Some comments"
jpeg.Metadata.Title = "A title"
jpeg.Save()
' Saves the jpeg in-place
jpeg.SaveAs(someNewPath)
' Saves with a new path
Here is the class:
Public Class JpegMetadataAdapter
Private ReadOnly path As String
Private frame As BitmapFrame
Public ReadOnly Metadata As BitmapMetadata
Public Sub New(path As String)
Me.path = path
frame = getBitmapFrame(path)
Metadata = DirectCast(frame.Metadata.Clone(), BitmapMetadata)
End Sub
Public Sub Save()
SaveAs(path)
End Sub
Public Sub SaveAs(path As String)
Dim encoder As New JpegBitmapEncoder()
encoder.Frames.Add(BitmapFrame.Create(frame, frame.Thumbnail, Metadata, frame.ColorContexts))
Using stream As Stream = File.Open(path, FileMode.Create, FileAccess.ReadWrite)
encoder.Save(stream)
End Using
End Sub
Private Function getBitmapFrame(path As String) As BitmapFrame
Dim decoder As BitmapDecoder = Nothing
Using stream As Stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
decoder = New JpegBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad)
End Using
Return decoder.Frames(0)
End Function
End Class

vb.net AES decryption returns "data is incomplete block"

I'm aware of the other thread on this issue (AES decryption error " The input data is not a complete block." Error vb.net), but I'm either not implementing the solutions offered there correctly, or something about my particular variant of this issue isn't covered by those solutions. In any event I'm getting the incomplete block error from the following code
Private GD As System.Security.Cryptography.Aes = System.Security.Cryptography.Aes.Create
Private PDB As New System.Security.Cryptography.Rfc2898DeriveBytes(EK, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
Public Function Decrypt(ByVal val As String) As String
Dim ret As String = Nothing
Dim TTB As New System.Text.UTF8Encoding
Try
Dim input() As Byte = TTB.GetBytes(val)
Using ms As New System.IO.MemoryStream(input)
Using cs As New System.Security.Cryptography.CryptoStream(ms, GD.CreateDecryptor(PDB.GetBytes(32), PDB.GetBytes(16)), Security.Cryptography.CryptoStreamMode.Read)
Using sr As New System.IO.StreamReader(cs)
ret = sr.ReadToEnd()
End Using
End Using
End Using
input = nothing
Catch ex As Exception
EL.AddErr("Encountered an error while decrypting the provided text for " & FName & ". Error Details: " & ex.Message, path)
End Try
Return ret
End Function
EK is my key, which I'll not be including. It's just a String though, nothing special.
I've tried several other methods to decrypt based on guidance on the MSDN site, DreamInCode, etc. None worked, but they all had different issues (typically returning a blank string). Seeing as this version of code closely mirrors my encryption code, I'd like to stick with it (or at least as close as I can while still having functional code).
Despite all comments, I still lack understanding of your intentions. Therefore, the sample code below may not provide what you exactly want, but at least should give an idea how to employ cryptographic functions. Particularly, the most notable difference from your approach is that the encryption key and initialization vector are computed once and for all messages, rather than reevaluated on each occasion, because the latter is prone to synchronization errors — such as when you reuse single crypto object to communicate with multiple parties, or when some messages get lost in transmission.
Public Shared Sub Test()
' Note: You should not actually hard-code any sensitive information in your source files, ever!
Dim sKeyPreimage As String = "MySuperPassword"
Dim oMyCrypto As New MyCrypto(sKeyPreimage)
Dim sPlaintext As String = "My super secret data"
Dim sEncrypted As String = oMyCrypto.EncryptText(sPlaintext)
Dim sDecrypted As String = oMyCrypto.DecryptText(sEncrypted)
Console.Out.WriteLine("Plaintext: {0}", sPlaintext) ' "My super secret data"
Console.Out.WriteLine("Encrypted: {0}", sEncrypted) ' "72062997872DC4B4D1BCBF48D5D30DF0D498B20630CAFA28D584CCC3030FC5F1"
Console.Out.WriteLine("Decrypted: {0}", sDecrypted) ' "My super secret data"
End Sub
Public Class MyCrypto
Private Shared TextEncoding As Text.Encoding = Text.Encoding.UTF8
Private CipherEngine As System.Security.Cryptography.SymmetricAlgorithm
' Note: Unlike in the question, same key and IV are reused for all messages.
Private CipherKey() As Byte
Private CipherIV() As Byte
Public Sub New(ByVal sKeyPreimage As String)
Dim abKeyPreimage() As Byte = TextEncoding.GetBytes(sKeyPreimage)
Dim abKeySalt() As Byte = TextEncoding.GetBytes("Ivan Medvedev")
Const KeyDerivationRounds As Integer = 1 << 12
Dim oKeyDerivationEngine As New System.Security.Cryptography.Rfc2898DeriveBytes(abKeyPreimage, abKeySalt, KeyDerivationRounds)
Me.CipherEngine = System.Security.Cryptography.Aes.Create()
Me.CipherEngine.Padding = Security.Cryptography.PaddingMode.PKCS7
Me.CipherKey = oKeyDerivationEngine.GetBytes(Me.CipherEngine.KeySize >> 3)
Me.CipherIV = oKeyDerivationEngine.GetBytes(Me.CipherEngine.BlockSize >> 3)
End Sub
Public Function Encrypt(ByVal abPlaintext() As Byte) As Byte()
Dim abCiphertext() As Byte
Using hStreamSource As New System.IO.MemoryStream(abPlaintext),
hStreamCipher As New System.Security.Cryptography.CryptoStream(
hStreamSource,
Me.CipherEngine.CreateEncryptor(Me.CipherKey, Me.CipherIV),
Security.Cryptography.CryptoStreamMode.Read),
hStreamTarget As New System.IO.MemoryStream
hStreamCipher.CopyTo(hStreamTarget)
abCiphertext = hStreamTarget.ToArray()
End Using
Return abCiphertext
End Function
Public Function Decrypt(ByVal abCiphertext() As Byte) As Byte()
Dim abPlaintext() As Byte
Using hStreamSource As New System.IO.MemoryStream(abCiphertext),
hStreamCipher As New System.Security.Cryptography.CryptoStream(
hStreamSource,
Me.CipherEngine.CreateDecryptor(Me.CipherKey, Me.CipherIV),
Security.Cryptography.CryptoStreamMode.Read),
hStreamTarget As New System.IO.MemoryStream
hStreamCipher.CopyTo(hStreamTarget)
abPlaintext = hStreamTarget.ToArray()
End Using
Return abPlaintext
End Function
Public Function EncryptText(ByVal sPlaintext As String) As String
Dim abPlaintext() As Byte = TextEncoding.GetBytes(sPlaintext)
Dim abCiphertext() As Byte = Me.Encrypt(abPlaintext)
Dim sCiphertext As String = Hex.Format(abCiphertext)
Return sCiphertext
End Function
Public Function DecryptText(ByVal sCiphertext As String) As String
Dim abCiphertext() As Byte = Hex.Parse(sCiphertext)
Dim abPlaintext() As Byte = Me.Decrypt(abCiphertext)
Dim sPlaintext As String = TextEncoding.GetChars(abPlaintext)
Return sPlaintext
End Function
End Class
Public Class Hex
Public Shared Function Format(ByVal abValue() As Byte) As String
Dim asChars(0 To abValue.Length * 2 - 1) As Char
Dim ndxChar As Integer = 0
For ndxByte As Integer = 0 To abValue.Length - 1
Dim bNibbleHi As Byte = abValue(ndxByte) >> 4, bNibbleLo As Byte = CByte(abValue(ndxByte) And &HFUS)
asChars(ndxChar) = Convert.ToChar(If(bNibbleHi <= 9, &H30US + bNibbleHi, &H37US + bNibbleHi)) : ndxChar += 1
asChars(ndxChar) = Convert.ToChar(If(bNibbleLo <= 9, &H30US + bNibbleLo, &H37US + bNibbleLo)) : ndxChar += 1
Next
Return New String(asChars)
End Function
Public Shared Function Parse(ByVal sValue As String) As Byte()
If String.IsNullOrEmpty(sValue) Then Return New Byte() {}
If (sValue.Length Mod 2) > 0 Then Return Nothing
Dim ndxText As Integer = 0
Dim ndxByteMax As Integer = (sValue.Length \ 2) - 1
Dim abValue(0 To ndxByteMax) As Byte
Try
For ndxByte As Integer = 0 To ndxByteMax
abValue(ndxByte) = Convert.ToByte(sValue.Substring(ndxText, 2), 16)
ndxText += 2
Next
Catch ex As Exception
Return Nothing
End Try
Return abValue
End Function
End Class
Again, please, note that this is just an example. I am not endorsing any kind of protection techniques shown here, especially because your task remains unknown. The code above simply illustrates the syntax and semantics — not how to do it right.

store and play microphone data in real time vb.net

as the title says, i'm trying to store and play microphone data in real time with vb.net 2010 and NAudio library. I got this code in C# from the NAudio Codeplex website and i translated it in vb.net.
There's no error in the code and the program works (i put a counter that keeps increasing and updating a label each time mic data is available to see if it's actually working), but i can't hear anything.
here is the code
Imports NAudio
Imports System.IO
'Libraries I'm using
Private Sub wi_dataAvailable(ByVal obj As Object, ByVal e As Wave.WaveInEventArgs) Handles wi.DataAvailable
count += 1 'here is where the counter increases
Label1.Text = count 'and here the label is updated and it seems to work fine
play_packet(e.Buffer)
End Sub
Private Sub play_packet(ByVal DR() As Byte)
Dim MS As New MemoryStream(DR)
Dim frmt As New Wave.WaveFormat
frmt = Wave.WaveFormat.CreateALawFormat(8000, 1)
Dim rsws As New Wave.RawSourceWaveStream(MS, frmt)
Dim pcms As Wave.WaveStream = Wave.WaveFormatConversionStream.CreatePcmStream(rsws)
Dim m_bwp As New Wave.BufferedWaveProvider(New Wave.WaveFormat(8000, 16, 1))
Dim dec() As Byte = cnssb(pcms)
m_bwp.AddSamples(dec, 0, dec.Length)
Dim latency As Integer
Dim cbi As Wave.WaveCallbackInfo = Wave.WaveCallbackInfo.NewWindow
Dim out_dev As New Wave.WaveOut(cbi)
out_dev.DesiredLatency = latency
out_dev.Init(m_bwp)
out_dev.Play()
End Sub
Private Function cnssb(ByVal nss As Wave.WaveStream) As Byte()
Dim memstr As New MemoryStream
Dim buff(1024) As Byte
Dim bytes As Integer
bytes = nss.Read(buff, 0, buff.Length)
While bytes > 0
memstr.Write(buff, 0, bytes)
bytes = nss.Read(buff, 0, buff.Length)
End While
Dim by() As Byte = memstr.ToArray
Return by
End Function
hope you can help me!
You shouldn't be creating a new WaveOut and BufferedWaveProvider every time a recorded buffer is received. Instead create one of each, and just add the audio into the BufferedWaveProvider as you receive it.
Solved!
I declared a boolean variable and then i edited the play_packet function like this:
dim initialized as boolean
'in the form load i set the variable to false
'and then here is the function
Private Sub play_packet(ByVal DR() As Byte)
Dim MS As New MemoryStream(DR)
Dim dec() As Byte = MS.ToArray
m_bwp.AddSamples(dec, 0, dec.Length)
MS.Close()
MS.Dispose()
Dim latency As Integer = 50
Dim cbi As Wave.WaveCallbackInfo = Wave.WaveCallbackInfo.NewWindow
Dim out_dev As New Wave.DirectSoundOut
out_dev.Volume = 1
If initialized = False Then
out_dev.Init(m_bwp)
out_dev.Play()
initialized = True
End If
End Sub