Pergunta

ATUALIZADO ABAIXO

Estou lendo um arquivo binário usando BinaryReader em VB.NET.A estrutura de cada linha do arquivo é:

    "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)

O problema é que o campo "Texto" possui alguns caracteres estranhos usados ​​para preenchimento.A maioria parece ser 0x00 caracteres nulos.

  1. Existe alguma maneira de se livrar desses caracteres 0x00 por alguma codificação?

  2. Caso contrário, como posso substituir a matriz chText para me livrar dos caracteres 0x00?Estou tentando serializar a tabela de dados resultante para XML e está falhando nesses caracteres não compatíveis.Consigo percorrer o array, porém não consigo descobrir como fazer a substituição?

ATUALIZAR:

É aqui que estou com muita ajuda dos rapazes/garotas abaixo.A primeira solução funciona, porém não tão flexível quanto eu esperava, a segunda falha para um caso de uso, porém é muito mais genérica.

Anúncio 1) Posso resolver o problema passando a string para esta sub-rotina

    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

Anúncio 2) Esta rotina elimina vários caracteres incorretos, mas falha em 0x00.Isto foi adaptado do 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
Foi útil?

Solução

Primeiro de tudo você deve descobrir qual é o formato do texto, para que você esteja apenas removendo algo às cegas, sem saber o que acertou.

Dependendo do formato, você usa métodos diferentes para remover os caracteres.

Para remover apenas os caracteres zero:

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)

Para remover tudo, desde o primeiro caractere zero até o final do array:

Dim len As Integer
While len < byText.Length AndAlso byText(len) <> 0
   len += 1
End While
strText = Encoding.ASCII.GetChars(byText, 0, len)

Editar:
Se você quiser apenas manter qualquer lixo que seja caracteres 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)

Outras dicas

Se os caracteres nulos forem usados ​​como preenchimento direito (ou seja, encerrando) o texto, o que seria o caso normal, isso é bastante fácil:

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

Se não, você ainda pode fazer um normal Replace na corda.Seria um pouco mais “limpo” se você fizesse a poda na matriz de bytes, antes convertendo-o em uma string.O princípio permanece o mesmo, no entanto.

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)

Você pode usar uma estrutura para carregar os dados:

[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;
}

Você deve ajustar o argumento UnknownType para se adequar à sua codificação de string.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top