2009-09-14 6 views
19

Donc, voici l'affaire: J'essaie d'ouvrir un fichier (à partir de bytes), le convertir en une chaîne afin que je puisse jouer avec des métadonnées dans l'en-tête, le convertir aux octets, et enregistrez-le. Le problème que je rencontre actuellement est avec ce code. Lorsque je compare la chaîne qui a été convertie d'avant en arrière (mais pas autrement modifiée) au tableau d'octets d'origine, elle est inégale. Comment puis-je faire ce travail?Conversion de tableau d'octets en chaîne et de retour en C#

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 ce UTF-8, en utilisant:

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

qui retourne "System.Text.UTF8Encoding".

+6

êtes-vous sûr que son UTF-8 pour commencer? –

+0

Je ne suis pas certain. Comment dirais-je si c'est le cas ou pas? –

+0

Que voulez-vous dire, c'est inégale? Votre chaîne est inégale? vous n'obtenez pas le même résultat de chaîne? – Khan

Répondre

16

Essayez les fonctions statiques de la classe Encoding qui vous fournit des instances des divers codages. Vous ne devriez pas avoir besoin d'instancier le Encoding juste pour convertir vers/depuis un tableau d'octets. Comment comparez-vous les chaînes dans le code?

Modifier

Vous comparez des tableaux, et non des chaînes. Ils sont inégaux parce qu'ils se réfèrent à deux tableaux différents; l'opérateur == compare uniquement ses 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; 
} 
+0

J'ai modifié la question pour montrer comment ... le code n'apparaît pas dans le commentaire! –

+0

J'ai essayé cela, ils reviennent qu'ils ne sont pas de la même longueur. Ça doit être ailleurs. –

+3

Regardez la documentation pour l'encodage UTF8. Il y a une possibilité de spécifier ou non le préambule. Si vous trouvez que votre tableau d'octets généré est plus long que l'original, alors c'est probablement votre problème. Encore une fois, vous devez vous assurer que UTF8 est, en fait, le bon codage. Quant à savoir comment vous pouvez le dire, vous devrez demander à celui qui vous fournit les données. –

3

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

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

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

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes)); 
5

En raison du fait que les chaînes .NET utilisent des chaînes Unicode, vous ne pouvez plus faire ce peuple comme l'ont fait en C. Dans la plupart des cas, vous ne devriez pas même tentative de aller en arrière de la chaîne < -> tableau d'octets sauf si le contenu est en fait texte.

Je dois préciser ce point: Dans .NET, si les données ne sont pas byte[]texte, alors ne tentez pas de le convertir en un string sauf pour le codage Base64 spécial pour les données binaires sur un texte canal. C'est un malentendu largement répandu parmi les personnes qui travaillent dans .NET.

+4

Chaîne <-> Les conversions byte [] doivent généralement être effectuées via l'une des classes System.Text.Encoding, et non par la classe BitConverter. BitConverter.ToString convertit un tableau d'octets en une représentation en chaîne hexadécimale des nombres, il ne convertit pas ** un tableau d'octets en une chaîne. –

+1

Hé, j'aurais dû supprimer cette ligne une fois que je savais que ce n'était pas le sujet de mon article. –

7

Lorsque vous avez octets bruts (8 bits caractères éventuellement, non imprimables) et que vous voulez les manipuler comme une chaîne .NET et les retransformer en octets, vous pouvez le faire en utilisant

Encoding.GetEncoding(1252) 

au lieu de UTF8Encoding. Ce codage fonctionne pour prendre n'importe quelle valeur de 8 bits et le convertir en un char .NET 16 bits, et vice-versa, sans perdre aucune information.Dans le cas spécifique que vous décrivez ci-dessus, avec un fichier binaire, vous ne pourrez pas "manipuler les métadonnées dans l'en-tête" et faire en sorte que les choses fonctionnent correctement, sauf si la longueur des données est inchangée. Par exemple, si l'en-tête contient

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

et que vous voulez changer ABC DEF, qui 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 (en substance) déplacer tout un octet plus loin vers la droite. Dans un fichier binaire typique, cela gâchera beaucoup les choses. Si les octets après "ABC" sont des espaces ou des caractères nuls, il est plus probable que l'écriture de données de remplacement plus importantes ne causera pas de problèmes - mais vous ne pouvez toujours pas remplacer ABC par WXYZ dans la chaîne .NET - vous devrez remplacer ABC {whatever_follows_it} par WXYZ. Cela étant, vous pourriez trouver qu'il est plus facile de laisser les données en octets et d'écrire les données de remplacement un octet à la fois.

+0

Si on a un tableau d'octets et souhaite remplacer toutes les occurrences d'une séquence particulière par une autre séquence d'une longueur différente (par exemple remplacer toutes les occurrences de {0x7D, 0x5E} par {0x7E}), convertir en chaîne, en utilisant 'String .Remplacer », puis convertir en une approche raisonnable? Est-ce que le codage susmentionné remplacerait chaque valeur d'octet 0-255 par le code de même numéro correspondant [le fait que l'encodage soit sans perte n'implique pas en soi que]? – supercat

+0

@supercat - oui cette approche (à condition d'utiliser l'encodage 1252) fonctionnerait. Mais vous ne seriez toujours pas capable de le faire avec la plupart des formats de fichiers binaires pour les raisons mentionnées dans mon message. –

+0

Si l'on utilise des formats sensibles à la position, il faudrait évidemment s'assurer que les choses qui ne sont pas censées bouger ne le sont pas. Même alors, il y aurait des cas où 'String.Replace' semblerait utile si les chaînes" original "et" remplacement "avaient la même longueur. – supercat

Questions connexes