Pergunta

Então, aqui está o negócio: Eu estou tentando abrir um arquivo (de bytes), convertê-lo em uma corda para que eu possa mexer com alguns metadados no cabeçalho, convertê-lo de volta para bytes e salvá-lo. O problema que eu estou correndo em agora é com este código. Quando comparar a cadeia que tem sido convertido para trás e para a frente (mas não de outro modo modificado) para a matriz de bites originais, é desigual. Como posso fazer este trabalho?

public static byte[] StringToByteArray(string str)
{
    UTF8Encoding encoding = new UTF8Encoding();
    return encoding.GetBytes(str);
}

public string ByteArrayToString(byte[] input)
{
    UTF8Encoding enc = new UTF8Encoding();
    string str = enc.GetString(input);
    return str;
}

Aqui está como eu estou comparando-os.

byte[] fileData = GetBinaryData(filesindir[0], Convert.ToInt32(fi.Length));
string fileDataString = ByteArrayToString(fileData);
byte[] recapturedBytes = StringToByteArray(fileDataString);
Response.Write((fileData == recapturedBytes));

Eu tenho certeza que é UTF-8, usando:

StreamReader sr = new StreamReader(filesindir[0]);
Response.Write(sr.CurrentEncoding);

que retorna "System.Text.UTF8Encoding".

Foi útil?

Solução

Experimente as funções estáticas na classe Encoding que lhe fornece exemplos das várias codificações. Você não deve precisar instanciar a Encoding apenas para converter de / para um array de bytes. Como você está comparando as strings em código?

Editar

Você está comparando matrizes, não cordas. Eles são desiguais porque se referem a duas matrizes diferentes; usando o operador == só irá comparar as suas referências, não seus valores. Você vai precisar para inspecionar cada elemento da matriz, a fim de determinar se eles são equivalentes.

public bool CompareByteArrays(byte[] lValue, byte[] rValue)
{
    if(lValue == rValue) return true; // referentially equal
    if(lValue == null || rValue == null) return false; // one is null, the other is not
    if(lValue.Length != rValue.Length) return false; // different lengths

    for(int i = 0; i < lValue.Length; i++)
    {
        if(lValue[i] != rValue[i]) return false;
    }

    return true;
}

Outras dicas

Quando você tem bytes brutos (de 8 bits personagens possivelmente-não-imprimíveis) e quer manipulá-los como uma string .NET e transformá-los de volta em bytes, você pode fazê-lo usando

Encoding.GetEncoding(1252)

em vez de UTF8Encoding. Essa codificação trabalha para assumir qualquer valor de 8 bits e convertê-lo em um .NET de 16 bits char, e vice-versa, sem perder nenhuma informação.

No caso específico que você descreve acima, com um arquivo binário, você não será capaz de "mexer com metadados no cabeçalho" e funciona corretamente a menos que o comprimento dos dados que você mexer com permanece inalterada. Por exemplo, se o cabeçalho contém

{any}{any}ABC{any}{any}

e você quer mudar ABC para DEF, que deve funcionar como você gostaria. Mas se você quer mudar ABC para WXYZ, você terá que escrever sobre o byte que segue "C" ou você (na essência) mover tudo um byte mais à direita. Em um arquivo binário típico, que irá bagunçar as coisas muito.

Se os bytes após "ABC" são espaços ou caracteres nulos, há uma melhor chance de que a gravação de dados de reposição maiores não vai causar problemas - mas você ainda não pode simplesmente substituir ABC com WXYZ na cadeia de .NET, tornando-o mais - - você teria que substituir ABC {whatever_follows_it} com WXYZ. Dado que, você pode achar que é mais fácil apenas para deixar os dados como bytes e escrever os dados de substituição de um byte de cada vez.

Devido ao fato de que as cordas .NET utilizar cadeias de caracteres Unicode, você não pode mais fazer isso como as pessoas faziam em C. Na maioria dos casos, você não deve mesmo tentativa para ir e voltar da corda <->. matriz de bytes a menos que o conteúdo é realmente texto

eu tenho que esclarecer este ponto: Em .NET, se os dados byte[] não é texto , então não tente convertê-lo para um string exceto para o especial Base64 codificação para dados binários mais de um canal de texto. Este é um equívoco muito generalizada entre as pessoas que trabalham em .NET.

Seu problema parece ser a maneira que você está comparando a matriz de bytes:

Response.Write((fileData == recapturedBytes));

Esta será sempre retornar falso desde que você está comparando o endereço da matriz de bytes, não os valores que ele contém. Comparar os dados de cadeia, ou usar um método de comparação das matrizes de bytes. Você também pode fazer isso em vez disso:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top