Вопрос

ОБНОВЛЕНО НИЖЕ

Я читаю двоичный файл с помощью 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 нулевых символов.

  1. Есть ли какой-нибудь способ избавиться от этих символов 0x00 с помощью какой-либо кодировки?

  2. В противном случае, как я могу выполнить замену в массиве 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 в соответствии с вашей строковой кодировкой.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top