Question

Alors voici le problème: j'essaie d'ouvrir un fichier (à partir d'octets), de le convertir en chaîne afin de pouvoir manipuler certaines métadonnées dans l'en-tête, de les reconvertir en octets et de les sauvegarder. Le problème que je rencontre actuellement concerne ce code. Lorsque je compare la chaîne qui a été convertie dans les deux sens (mais non autrement modifiée) au tableau d'octets d'origine, c'est inégal. Comment puis-je faire ce travail?

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

Voici comment je les compare.

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

Je suis sûr que c'est du UTF-8, avec:

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

qui retourne & "System.Text.UTF8Encoding &";

Était-ce utile?

La solution

Essayez les fonctions statiques de la classe Encoding qui vous fournit des instances des différents encodages. Vous ne devriez pas avoir besoin d’instancier le == juste pour convertir en / à partir d’un tableau d’octets. Comment comparez-vous les chaînes dans le code?

Modifier

Vous comparez des tableaux, pas des chaînes. Ils sont inégaux car ils font référence à deux tableaux différents; l’utilisation de l’opérateur <=> ne fera que comparer leurs références, pas leurs valeurs. Vous devrez inspecter chaque élément du tableau afin de déterminer s’ils sont équivalents.

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

Autres conseils

Lorsque vous avez des octets bruts (caractères 8 bits éventuellement non imprimables) et que vous souhaitez les manipuler en tant que chaîne .NET et les reconvertir en octets, vous pouvez le faire en utilisant

Encoding.GetEncoding(1252)

au lieu de UTF8Encoding. Ce codage fonctionne en prenant n'importe quelle valeur 8 bits et en le convertissant en un caractère .NET 16 bits, et inversement, sans perdre aucune information.

Dans le cas spécifique que vous décrivez ci-dessus, avec un fichier binaire, vous ne pourrez pas & "falsifier les métadonnées dans l'en-tête &"; et que tout fonctionne correctement, à moins que la longueur des données que vous importez ne soit pas modifiée. Par exemple, si l'en-tête contient

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

et que vous voulez changer ABC en DEF, cela devrait fonctionner comme vous le souhaitez. Mais si vous voulez changer ABC en WXYZ, vous devrez écrire sur l'octet qui suit & "C &"; ou vous allez (en substance) déplacer tout d'un octet plus à droite. Dans un fichier binaire typique, cela gâchera grandement les choses.

Si les octets après " ABC " Si des espaces ou des caractères nuls sont présents, il est plus probable que l’écriture de données de remplacement volumineuses ne pose pas de problème - mais vous ne pouvez toujours pas remplacer ABC par WXYZ dans la chaîne .NET, ce qui allonge la durée - vous devrez remplacer ABC {any_follows_it} avec WXYZ. Dans ces conditions, vous constaterez peut-être qu'il est plus simple de laisser les données sous forme d'octets et d'écrire les données de remplacement, octet par octet.

En raison du fait que les chaînes .NET utilisent des chaînes Unicode, vous ne pouvez plus le faire, contrairement à ce qui se passait en C. Dans la plupart des cas, vous ne devriez même pas tenter de revenir en arrière dans string < ; - > tableau d'octets, sauf si le contenu est réellement du texte .

Je dois préciser ce point: dans .NET, si les données octet [] ne sont pas du texte , ne tentez pas pour le convertir en chaîne , à l'exception de l'encodage spécial Base64 pour données binaires sur un canal de texte. Il s'agit d'un malentendu largement répandu parmi les personnes travaillant dans .NET.

Votre problème semble être la façon dont vous comparez le tableau d'octets:

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

Cela retournera toujours faux puisque vous comparez l'adresse du tableau d'octets, pas les valeurs qu'il contient. Comparez les données de chaîne ou utilisez une méthode de comparaison des tableaux d'octets. Vous pouvez également le faire à la place:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top