I'm trying to convert some functions written in JScript to VB.NET (I'm porting a classic ASP page to ASP.NET) and having issues as I'm not very familiar with JScript. I'm having issues with converting even the function declaration properly in VB.NET. In my converted code VS2008 is giving me an error saying "Array bounds can not be specified in type identifiers". I don't know how to modify my function declaration to return an Array but ALSO accept an array as input as the JScript declaration does. Any ideas? Am I approaching this wrong?
Thanks in advance.
Here is one of the original JScript functions:
function binl2byt(binarray)
{
var hex_tab = "0123456789abcdef";
var bytarray = new Array(binarray.length * 4);
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
bytarray[i] = (binarray[i>>2] >> ((i%4)*8+4) & 0xF) << 4 | binarray[i>>2] >> ((i%4)*8) & 0xF;
}
return bytarray;
}
Here is what I have in VB.NET so far:
Public Function binl2byt() As Array(byval binarray as array)
Dim hex_tab As String = "0123456789abcdef"
Dim bytarray() As Byte
Dim str As String = ""
For I As Integer = 0 To (bytarray.Length * 4) Step 1
bytarray(I) = ((binarray(I >> 2) >> ((I Mod (4)) * 8 + 4) & Oxf) << 4) Or (binarray(I >> 2) >> ((I Mod (4) * 8) & OxF))
Next
Return bytarray
End Function
There is no need for this function, it is already there in .NET for you.
BitConverter.ToString(Bytes);
Where Bytes is your byte array.
Related
I am writing a program which needs to read MIDI files. The program reads each series of bytes for each track into a byte array, which is passed into a contructor for a "Track" object. The track object then reads the array and interprets MIDI events from the data.
I became aware of a problem after intense inspection of the program. It seems that sometimes, the byte signalling a MIDI meta-event: 0xFF, is being read as part of the delta time, leading the program to believe it is reading a channel-voice event which then causes errors when interpreting the following event data.
I believe that the trouble is being caused by my function that reads Variable Length Quantities including delta time. I have tried using the function given by the MIDI specification on page 11/12 (converted from C to VB.net with my very limited C knowledge):
Private Function getVariableLengthValue(ByRef currentByte As Integer) As Double
val = data(currentByte)
currentByte += 1
If val & &H80 Then
val = val & &H7F
Do
val = (val << 7) + (data(currentByte) & &H7F)
currentByte += 1
Loop While data(currentByte) & &H80
End If
getVariableLengthValue = val
End Function
as well as my own ugly function developed by reading the Wikipedia page on VLQs
Private Function getVariableLengthValue(ByRef currentByte As Integer) As Double
Dim val As Double = 0
Dim varLengthBytes As New List(Of Byte)
While getMostSigBit(data(currentByte)) = 1
varLengthBytes.Add(data(currentByte))
currentByte += 1
End While
Dim finalByte As Byte = data(currentByte)
varLengthBytes.Add(finalByte)
currentByte += 1
Dim varLengthString As String = ""
If varLengthBytes.Count > 1 Then
For x As Integer = 0 To varLengthBytes.Count - 2
Dim byteString As String = Convert.ToString(varLengthBytes(x), 2)
byteString = byteString.Remove(0, 1)
While byteString.Length < 7
byteString = byteString.Insert(0, "0")
End While
varLengthString = varLengthString + byteString
Next
End If
Dim finalByteString As String = Convert.ToString(varLengthBytes(varLengthBytes.Count - 1), 2)
finalByteString = finalByteString.Remove(0, 1)
While finalByteString.Length < 7
finalByteString = finalByteString.Insert(0, "0")
End While
varLengthString = varLengthString + finalByteString
val = Convert.ToInt64(varLengthString, 2)
getVariableLengthValue = val
End Function
however both seem to give the same issue: reading too far into the data, overspilling the delta time and reading in the event type, knocking the rest of the code out of step with the data being read.
If anybody could help highlight the flaw with my C conversion, I would greatly appreciate it.
I am somewhat new to coding and very new to Stack Overflow, so sorry for any unnecessary or lacking detail. I'l do my best to provide further information.
Many thanks, Roy H
I'm trying to split a string of 32 numerical characters into a 16 length Array of Byte and each value has to stay numerical
from "70033023311330000000004195081460" to array {&H_70, &H_03, &H_30, &H_23, ..}
I've tried multiple stuff but each time either it's the conversion that's wrong or I can't find the appropriate combination of functions to implement it.
'it splits but per 1 character only instead of two
str.Select(Function(n) Convert.ToByte(n, 10)).ToArray
'I also tried looping but then the leading zero disappears and the output is a string converted to HEX which is also not what I want.
Function ConvertStringToHexBinary(str As String) As Byte()
Dim arr(15) As Byte
Dim k = 0
For i As Integer = 0 To str.Length - 1
arr(k) = str(i) & str(i + 1)
k += 1
i += 1
Next
Return arr
End Function
Anyone got any suggestion what to do?
G3nt_M3caj's use of LINQ might be.. er.. appealing to the LINQ lovers but it's horrifically inefficient. LINQ is a hammer; not everything is a nail.
This one is about 3 times faster than the LINQ version:
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length/2) as Byte
For i = 0 to str.Length - 1 Step 2
byt(i/2) = Convert.ToByte(str.Substring(i, 2))
Next i
And this one, which does it all with math and doesn't do any new stringing at all is just under 3 times faster than the above (making it around 9 times faster than the LINQ version):
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length / 2) As Byte
For i = 0 To str.Length - 1
If i Mod 2 = 0 Then
byt(i / 2) = (Convert.ToByte(str(i)) - &H30) * &HA
Else
byt(i / 2) += Convert.ToByte(str(i)) - &H30
End If
Next i
Of the two, I prefer the stringy version because it's easier to read and work out what's going on - another advantage loops approaches often have over a LINQ approach
Do you need something like this?
Dim str As String = "70033023311330000000004195081460"
Dim mBytes() As Byte = str.
Select(Function(x, n) New With {x, n}).
GroupBy(Function(x) x.n \ 2, Function(x) x.x).
Select(Function(y) Convert.ToByte(New String(y.ToArray()), 10)).ToArray
I'm trying to compute the password expiry date, and most of the example code is in C#
One sample has:
IADsLargeInteger largeInt;
largeInt = (IADsLargeInteger) largeIntVal;
myLong = (long)largeInt.HighPart << 32 | (uint)largeInt.LowPart;
If I try something similar in VB.net:
dim myLong as Long
myLong = largeInt.HighPart << 32 Or largeInt.LowPart
Then I seem to get an invalid value. How can I obtain similar results in VB?
According to this the problem is because VB.Net has no unsigned integer class.
The solution is:
props = resultDE.Properties("pwdLastSet")
Dim prop As ActiveDs.LargeInteger
prop = props(0)
Dim int64Value As Long
Dim strTemp As String
strTemp = "&H" + CStr(Hex(prop.HighPart)) + CStr(Hex(prop.LowPart))
int64Value = Val(strTemp)
I am learning visual basic .net and I am attempting to translate some java source code to a vb.net project. The project reads mp3 details and then splits the file accurately according to the frameheader details etc.
My question relates to reading the frame header of mp3 files. I understand that the frame details are contained in the first 4 (32-bits) bytes of a frame and certain bits represent certain values as detailed here: http://www.mp3-tech.org/programmer/frame_header.html
Using FileStream I have been able to read this data and display it in binary within a text box.
I am looking for help on reading the bits and assigning them to variables within my class. I am not sure what would be the correct procedure to do this as some values as 1, 2 or 4 bits in length e.g. bits 19-20 = MpegType, bits 12-15 = BitrateIndex, bit 9 = Padding etc.
I have looked at similar projects available on codeproject.com but I do not understand how they have achieved the above.
Any help is much appreciated.
EDIT:
Here is the main sub so far, I have not included the code declaring variables and properties etc.
Public Sub decode()
Dim fs As FileStream
Dim bytes(3) As Byte
fs = New FileStream(mFilename, FileMode.Open, FileAccess.Read)
If fs.CanRead Then
fs.Read(bytes, 0, bytes.Length)
For i As Integer = 0 To bytes.Length - 1
Form1.RichTextBox.Text += Convert.ToString(bytes(i), 2).PadLeft(8, "0"c) & vbCrLf
Next
fs.Close()
fs.Dispose()
Else
MsgBox("File CANNOT be read!!!")
End If
End Sub
When this is run the output in the rich text box is as follows:
11111111
11111010
10110011
01001100
I want to read through these bits and assign the appropriate values to the variables e.g.
Read the first 12 bits for sync value.
Read bit 13 for mpegID value.
Read bit 14 and 15 for layerID value etc.
Hope that is clearer.
The java code is as follows:
public FrameHeader() {
this.header32 = 0;
valid = false;
}
public FrameHeader(int header32) {
this.header32 = header32;
decode();
}
public void setHeader32(int header32) {
this.header32 = header32;
decode();
}
private void decode() {
mpegID = (header32 >> 19) & 3;
layerID = (header32 >> 17) & 3;
crc16used = (header32 & 0x00010000) == 0;
bitrateIndex = (header32 >> 12) & 0xF;
samplingrateIndex = (header32 >> 10) & 3;
padding = (header32 & 0x00000200) != 0;
privateBitSet = (header32 & 0x00000100) != 0;
mode = (header32 >> 6) & 3;
modeExtension = (header32 >> 4) & 3;
copyrighted = (header32 & 0x00000008) != 0;
original = (header32 & 0x00000004) == 0; // bit set -> copy
emphasis = header32 & 3;
valid = (mpegID != ILLEGAL_MPEG_ID) && (layerID != ILLEGAL_LAYER_ID) && (bitrateIndex != 0)
&& (bitrateIndex != 15) && (samplingrateIndex != ILLEGAL_SR);
if (valid) {
samplingrateHz = SAMPLING_RATES[samplingrateIndex];
if (mpegID == MPEG2_ID)
samplingrateHz >>= 1; // 16,22,48 kHz
if (mpegID == MPEG25_ID)
samplingrateHz >>= 2; // 8,11,24 kHz
channels = (mode == MODE_MONO) ? 1 : 2;
bitrateKBPS = BITRATE_MAP[mpegID][layerID][bitrateIndex];
if (layerID == LAYER1_ID) {
// layer 1: always 384 samples/frame and 4byte-slots
samplesPerFrame = 384;
bytesPerSlot = 4;
}
else {
// layer 2: always 1152 samples/frame
// layer 3: MPEG1: 1152 samples/frame, MPEG2/2.5: 576
// samples/frame
samplesPerFrame = ((mpegID == MPEG1_ID) || (layerID == LAYER2_ID)) ? 1152 : 576;
bytesPerSlot = 1;
}
frameSize = ((bitrateKBPS * 125) * samplesPerFrame) / samplingrateHz;
if (bytesPerSlot > 1)
frameSize -= frameSize % bytesPerSlot;
if (padding)
frameSize += bytesPerSlot;
}
}
Here is a detailed explanation of frames and a formula on how data is held in the header, the first 4 bytes of a frame.
I am not sure what you are trying to accomplish but, just in case, here you go. There is no point in reinventing the wheel.
.Net has class called BitArray that you would use to store your bits.
I have come across a similar project that uses a function to converts bits to string. I've combined this code with another example I found that changed a binary string to integer. Interested to hear of alternative methods?
Public Function BinaryToInteger(ByVal objBitArray As BitArray, ByVal intStart As Integer, ByVal intEnd As Integer) As Integer
Dim BinaryString As String
Dim BinaryNum As Integer
Dim BitCount As Short
BinaryString = ""
For i As Integer = intStart To intEnd
BinaryString &= IIf(objBitArray.Item(i), "1", "0")
Next
For BitCount = 1 To Len(BinaryString)
BinaryNum = BinaryNum + (CDbl(Mid(BinaryString, Len(BinaryString) - BitCount + 1, 1)) * (2 ^ (BitCount - 1)))
Next BitCount
BinaryToInteger = BinaryNum
End Function
I want to use a FileStream and seek from the beginning of the file while moving forward in the file .01% of the file size at a time.
So I want to seek to a position in the file, read the entire line, if it matches my criteria I am done. If not, I seek ahead another .01.
C# is OK but VB.NET preferred.
I used to do it something like this in VB6...
FileOpen(1, CurrentFullPath, OpenMode.Input, OpenAccess.Read, OpenShare.Shared)
Dim FileLength As Long = LOF(1)
For x As Single = 0.99 To 0 Step -0.01
Seek(1, CInt(FileLength * x))
Dim S As String = LineInput(1)
S = LineInput(1)
filePosition = Seek(1)
If filePosition < 50000 Then
filePosition = 1
Exit For
End If
V = Split(S, ",")
Dim MessageTime As Date = CDate(V(3) & " " & Mid$(V(4), 1, 8))
Dim Diff As Integer = DateDiff(DateInterval.Minute, MessageTime, CDate(RequestedStartTime))
If Diff >= 2 Then
Exit For
End If
Next
But I don't want to use FileOpen, I want to use a FileStream.
Any help is greatly appreciated!
This is a more or less direct conversion of your code, where we use FileStream.Position to specify where in the file to read:
Using streamReader As System.IO.StreamReader = System.IO.File.OpenText(CurrentFullPath)
For x As Single = 0.99 To 0 Step -0.01
streamReader.BaseStream.Position = CLng(streamReader.BaseStream.Length * x)
Dim S As String = streamReader.ReadLine()
'... etc.
Next
End Using
what bout something like this (C# version):
using (var file = System.IO.File.OpenText(filename))
{
while (!file.EndOfStream)
{
string line = file.ReadLine();
//do your logic here
//Logical test - if true, then break
}
}
EDIT: VB version here (warning - from a C# dev!)
Using file as FileStream = File.OpenText(filename)
while Not file.EndOfStream
Dim line as string = file.ReadLine()
''//Test to break
''//exit while if condition met
End While
End Using
I normally prefer vb.net, but C#'s iterator blocks are slowly winning me over:
public static IEnumerable<string> SkimFile(string FileName)
{
long delta = new FileInfo(FileName).Length / 100;
long position = 0;
using (StreamReader sr = new StreamReader(FileName))
{
while (position < 100)
{
sr.BaseStream.Seek(position * delta, SeekOrigin.Begin);
yield return sr.ReadLine();
position++;
}
}
}
Put it in a class library project and use it from vb like this:
Dim isMatch as Boolean = False
For Each s As String in SkimFile("FileName.txt")
If (RequestedDate - CDate(s.SubString(3,11))).Minutes > 2 Then
isMatch = True
Exit For
End If
Next s
(I took some liberties with you criteria (assumed fixed-width values rather than delimited) to make the example easier)
There's an example on MSDN.
Edit in response to comment:
I must admit I'm a bit confused, as you seemed insistant on using a buffered FileStream, but want to read a file a line at a time? You can do that quite simply using a StreamReader. I don't know VB, but in C# it would be something like this:
using (StreamReader sr = File.OpenText(pathToFile))
{
string line = String.Empty;
while ((line = sr.ReadLine()) != null)
{
// process line
}
}
See http://msdn.microsoft.com/en-us/library/system.io.file.aspx.