0x00 в двоичном файле VB.NET
-
20-09-2019 - |
Вопрос
ОБНОВЛЕНО НИЖЕ
Я читаю двоичный файл с помощью BinaryReader в VB.NET.Структура каждой строки в файле выглядит следующим образом:
"Category" = 1 byte
"Code" = 1 byte
"Text" = 60 Bytes
Dim Category As Byte
Dim Code As Byte
Dim byText() As Byte
Dim chText() As Char
Dim br As New BinaryReader(fs)
Category = br.ReadByte()
Code = br.ReadByte()
byText = br.ReadBytes(60)
chText = encASCII.GetChars(byText)
Проблема в том, что поле "Текст" содержит несколько необычных символов, используемых для заполнения.В основном это 0x00 нулевых символов.
Есть ли какой-нибудь способ избавиться от этих символов 0x00 с помощью какой-либо кодировки?
В противном случае, как я могу выполнить замену в массиве chText, чтобы избавиться от символов 0x00?Я пытаюсь сериализовать результирующий datatable в XML, и это приводит к сбою из-за этих несоответствующих символов.Я могу перебирать массив, однако я не могу понять, как выполнить замену?
Обновить:
Это то, где я нахожусь с большой помощью от парней / девушек ниже.Первое решение работает, однако не такое гибкое, как я надеялся, второе не подходит для одного варианта использования, однако оно гораздо более универсальное.
Объявление 1) Я могу решить проблему, передав строку в эту подпрограмму
Public Function StripBad(ByVal InString As String) As String
Dim str As String = InString
Dim sb As New System.Text.StringBuilder
strNew = strNew.Replace(chBad, " ")
For Each ch As Char In str
If StrComp(ChrW(Val("&H25")), ch) >= 0 Then
ch = " "
End If
sb.Append(ch)
Next
Return sb.ToString()
End Function
Объявление 2) Эта процедура удаляет несколько символов-нарушителей, однако завершается неудачей при 0x00.Это было адаптировано из MSDN, http://msdn.microsoft.com/en-us/library/kdcak6ye.aspx.
Public Function StripBadwithConvert(ByVal InString As String) As String
Dim unicodeString As String
unicodeString = InString
' Create two different encodings.
Dim ascii As Encoding = Encoding.ASCII
Dim [unicode] As Encoding = Encoding.UTF8
' Convert the string into a byte[].
Dim unicodeBytes As Byte() = [unicode].GetBytes(unicodeString)
Dim asciiBytes As Byte() = Encoding.Convert([unicode], ascii, unicodeBytes)
Dim asciiChars(ascii.GetCharCount(asciiBytes, 0, asciiBytes.Length) - 1) As Char
ascii.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0)
Dim asciiString As New String(asciiChars)
Return asciiString
End Function
Решение
Прежде всего, вы должны выяснить, каков формат текста, чтобы вы просто вслепую удаляли что-то, не зная, на что вы нажмете.
В зависимости от формата вы используете различные методы для удаления символов.
Чтобы удалить только нулевые символы:
Dim len As Integer = 0
For pos As Integer = 0 To byText.Length - 1
If byText(pos) <> 0 Then
byText(len) = byText(pos)
len += 1
End If
Next
strText = Encoding.ASCII.GetChars(byText, 0, len)
Чтобы удалить все, начиная с первого нулевого символа и заканчивая концом массива:
Dim len As Integer
While len < byText.Length AndAlso byText(len) <> 0
len += 1
End While
strText = Encoding.ASCII.GetChars(byText, 0, len)
Редактировать:
Если вы просто хотите сохранить всякий мусор, который оказывается символами ASCII:
Dim len As Integer = 0
For pos As Integer = 0 To byText.Length - 1
If byText(pos) >= 32 And byText(pos) <= 127 Then
byText(len) = byText(pos)
len += 1
End If
Next
strText = Encoding.ASCII.GetChars(byText, 0, len)
Другие советы
Если нулевые символы используются в качестве правого заполнения (т.е. завершающий) текст, который был бы обычным случаем, это довольно легко:
Dim strText As String = encASCII.GetString(byText)
Dim strlen As Integer = strText.IndexOf(Chr(0))
If strlen <> -1 Then
strText = strText.Substr(0, strlen - 1)
End If
Если нет, вы все равно можете выполнить обычную Replace
на веревочке.Было бы немного “чище”, если бы вы выполнили обрезку в массиве байтов, до того , как преобразуем его в строку.Однако принцип остается тем же самым.
Dim strlen As Integer = Array.IndexOf(byText, 0)
If strlen = -1 Then
strlen = byText.Length + 1
End If
Dim strText = encASCII.GetString(byText, 0, strlen - 1)
Вы можете использовать структуру для загрузки данных:
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
internal struct TextFileRecord
{
[System.Runtime.InteropServices.FieldOffset(0)]
public byte Category;
[System.Runtime.InteropServices.FieldOffset( 1 )]
public byte Code;
[System.Runtime.InteropServices.FieldOffset( 2 )]
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr, SizeConst=60)]
public string Text;
}
Вы должны настроить аргумент UnmanagedType в соответствии с вашей строковой кодировкой.