Робота з байтами у VB.NET - ChrW, BitConverter.ToInt32, Convert.ToInt32, Byte.Parse, ToString("X2") / AllowHexSpecifier, GetBytes/GetString, New Byte(N) {}, UInt32 = &H33.
Це сторінка для самих початковців. На неї я опишу усі головні функції роботи з байтами у Бейсіці. Голові можливості Бейсіка підкреслені нище червоним колором. Якщо ви зможете написати першу функцию на Бейсіці без того, щоб подивитися у Інтернет - вважайте, що ви зрозуміли як працювати з байтами, символами та строками.
Почнемо з самої важкої функції - вона утворює різноманітни випадкові паролі. Усе починаеться з випадкового числа. І звичайно, деякі літери можливо вилучити в результату, бо наприклад, вони заважають подивитися на текст браузером (або з інших причин).
91: Public Function GetRandomInteger(MaxValue As Integer) As Integer
92: Dim byte_count As Byte() = New Byte(3) {}
93: Dim random_number As New System.Security.Cryptography.RNGCryptoServiceProvider()
94: random_number.GetBytes(byte_count)
95: Return (Math.Abs(BitConverter.ToInt32(byte_count, 0)) / Int32.MaxValue) * MaxValue
96: End Function
97:
98: Public Function CreateRandomPassword(Len As Integer, Optional FromChagCode As UInt32 = &H33, Optional ToCharCode As UInt32 = &H7E, Optional ExcludeChars As String = "<>") As String
99: Dim Ret1 As New System.Text.StringBuilder
100: While Ret1.Length < Len
101: Dim RandomNum As Integer = FromChagCode + GetRandomInteger(ToCharCode - FromChagCode)
102: Dim OneChar As Char = ChrW(RandomNum)
103: If Not ExcludeChars.Contains(OneChar) Then
104: Ret1.Append(OneChar)
105: End If
106: End While
107: Return Ret1.ToString
108: End Function
Копистуватися фукцією просто:
113: PassTextBox.Text = CreateRandomPassword(RandomPasswordLength)
Сторінка вийшлу дуже коротка, тому я додам сюда ще пару своїх корисних функцій для перетворення символів та байтів у строку. Ці дві функції виконують серіалізацію байтів у строку й навпаки строку у байти.
58: <Extension()>
59: Public Function BytesToHex(ByVal InputBytes As Byte()) As String
60: Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()
61: For i As Integer = 0 To InputBytes.Length - 1
62: sb.Append(InputBytes(i).ToString("X2"))
63: Next
64: Return sb.ToString()
65: End Function
66:
67: <Extension()>
68: Public Function HexStringToBytes(ByVal InputStr As String) As Byte()
69: Dim ButeArrLength As Integer = (InputStr.Length + 1) / 2
70: Dim OutArr(ButeArrLength) As Byte, I As Integer, OneByte As Byte
71: For I = 0 To InputStr.Length / 2 - 1
72: OneByte = Byte.Parse(InputStr.Substring(I * 2, 2), Globalization.NumberStyles.AllowHexSpecifier)
73: OutArr(I) = OneByte
74: Next
75: ReDim Preserve OutArr(I - 1)
76: Return OutArr
77: End Function
Наступна функція дуже корисна, коли строка має спеціфічні символи, які неможна побачити, або які частково взагалі усікаються.
48: <Extension()>
49: Public Function ToHexString(ByVal Input As String) As String
50: Dim InputBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(Input)
51: Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()
52: For i As Integer = 0 To InputBytes.Length - 1
53: sb.Append(InputBytes(i).ToString("X2"))
54: Next
55: Return sb.ToString()
56: End Function
Наступна функція теж дуже корисна, коли треба отримати звичайні байти замість Stream. Наприклад візьмемо будь який Stream.
Ви можете почитати його як Stream
104: Public Function ReadResource(ResourceName As String) As Byte()
105: Dim Asm1 As Assembly = Assembly.GetExecutingAssembly()
106: Dim Stream1 As IO.Stream = Asm1.GetManifestResourceStream(ResourceName)
107: Return Stream1.ToByteArray
108: End Function
і далі зробити з цього байтового потоку що завгодно.
5: <Extension()>
6: Public Function ToByteArray(ByVal stream As IO.Stream) As Byte()
7: stream.Position = 0
8: Dim buffer As Byte() = New Byte(stream.Length - 1) {}
9: Dim totalBytesCopied As Integer = 0
10:
11: While totalBytesCopied < stream.Length
12: totalBytesCopied += stream.Read(buffer, totalBytesCopied, Convert.ToInt32(stream.Length) - totalBytesCopied)
13: End While
14:
15: Return buffer
16: End Function
Наприклад нище я бажаю подивитися на визначення полей у базі EF.
Вони читаються як Stream, а потім з потока байтів за допомогою GetString утворюється строка.
Зрозуміло, що й навпаки будь яка строка у будь який момент може бути перетворена на набор байтів, як це зроблено багато разів вище.
Зробити це перетворення можна багатьма засобами, наприклад фунціями ASC та ASCW. Прога нише відбирає у тексті усі текстові константи та опрацьовує ті, у якиє є кірілліца.
67: Dim SourceVBCode As String = IO.File.ReadAllText(OneFileName)
68: Dim Reg1 As New Regex("""(.|\n)*?""")
69: Dim StringLiterals As MatchCollection = Reg1.Matches(SourceVBCode)
...
78: For Each OneRusLiteral As Match In StringLiterals
79: Dim HasCyrillic As Boolean = OneRusLiteral.Value.Where(Function(X) IsCyrillic(X)).Any
80: If HasCyrillic Then
...
105: End If
106: Next
...
166: Public Function IsCyrillic(c As Char) As Boolean
167: Return AscW(c) >= &H410 And AscW(c) <= &H44F
168: End Function
Також подивиться, будь ласка, як зробити транслітерацію з кіріліці. Найльш поширена на практиці задачка - це перейменування Windows-діректорій, але будь що можна робити точно так же.
Для цього нам буде потрібен ось такий словничок Translate.vb, та пару стрічок коду.
1: Module Program
2:
3: Dim Root As String = "J:\vb-net\Old\Last\MyFoto\MyFoto\"
4: Dim Tr As Translate = New Translate
5: Sub Main(args As String())
6: 'ReadFileList(Root)
7: ReadDirList(Root)
8: End Sub
9:
10: Sub ReadDirList(Dir As String)
11: For Each OneDir As String In IO.Directory.GetDirectories(Dir)
12: Dim Pos1 As Integer = OneDir.LastIndexOf("\")
13: Dim CyrPart As String = Mid(OneDir, Pos1 + 2)
14: Dim Arr1 As Byte() = Text.UTF8Encoding.UTF8.GetBytes(OneDir)
15: Dim New1 As New List(Of String)
16: For i As Integer = 0 To CyrPart.Length - 1
17: Try
18: New1.Add(Tr.Table(CyrPart(i)))
19: Catch ex As KeyNotFoundException
20: New1.Add(CyrPart(i))
21: End Try
22: Next
23: Console.WriteLine($"{OneDir}=>{Left(OneDir, Pos1 + 1) & String.Join("", New1)}")
24: Try
25: IO.Directory.Move(OneDir, Left(OneDir, Pos1 + 1) & String.Join("", New1))
26: Catch ex As Exception
27: Console.WriteLine(ex.Message)
28: End Try
29: 'ReadFileList(OneDir)
30: ' ReadDirList(OneDir)
31: Next
32: End Sub
33: End Module
Ще одне цікаве застосування різноманітних перетворень байтів у цілі числа при обробці IP-адреса. Тут цікаво, що байти у IP-адресах нумеруються у зворотньому напрямці стосовно цілих чисел у компутерах X86, тобто здавалося би що можливо просто трансформувати IP-адресу на ціле число, але ні, змінюватися буде не той байт що потрібен :
Коректний шлях роботи з IP-адресами ось такий:
632: Function GetIpRange(FromIp As String, ToIp As String) As List(Of String)
633: Dim IpRange As New List(Of String)
634: Dim Adr1 As UInt32 = BitConverter.ToUInt32(IPAddress.Parse(FromIp).GetAddressBytes.ToArray)
635: Dim Adr2 As UInt32 = BitConverter.ToUInt32(IPAddress.Parse(ToIp).GetAddressBytes.ToArray)
636: For I As Integer = 0 To 255
637: Dim ByteArr As Byte() = BitConverter.GetBytes(Adr1)
638: Dim IpAdr As IPAddress = IPAddress.Parse($"{ByteArr(0) }.{ByteArr(1)}.{ByteArr(2)}.{ByteArr(3) + I}")
639: IpRange.Add(IpAdr.ToString)
640: If IpAdr.ToString = ToIp Then Exit For
641: Next
642: Return IpRange
643: End Function