(NET) NET (2012)

Робота з байтами у 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


Comments ( )
Link to this page: //www.vb-net.com/RandomPassword/Index.htm
< THANKS ME>