web-dev-qa-db-ja.com

バイト配列を文字列に変換し、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;
}

以下は、それらを比較する方法です。

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

私はそれがUTF-8であると確信しています:

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

「System.Text.UTF8Encoding」を返します。

20
Brian Hicks

さまざまなエンコーディングのインスタンスを提供するEncodingクラスで静的関数を試してください。バイト配列との間で変換するためだけにEncodingをインスタンス化する必要はありません。コード内の文字列をどのように比較していますか?

編集

文字列ではなく配列を比較しています。 2つの異なる配列を参照するため、これらは等しくありません。 ==演算子は、値ではなく参照のみを比較します。それらが同等であるかどうかを判断するために、配列の各要素を検査する必要があります。

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;
}
16
Adam Robinson

生のバイト(8ビットの印刷できない可能性のある文字)があり、それらを.NET文字列として操作してバイトに戻す場合は、次のようにして実行できます。

Encoding.GetEncoding(1252)

uTF8Encodingの代わりに。このエンコーディングは、8ビット値を取得して.NET 16ビット文字に変換し、情報を失うことなく再び戻します。

上記の特定のケースでは、バイナリファイルを使用すると、「ヘッダーにメタデータが含まれている」ことができず、変更するデータの長さが変わらない限り、正しく機能しません。たとえば、ヘッダーに

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

aBCをDEFに変更したい場合、それはあなたが望むように機能するはずです。ただし、ABCをWXYZに変更する場合は、 "C"に続くバイトを上書きするか、(本質的に)すべてを1バイト右に移動する必要があります。典型的なバイナリファイルでは、それは物事を大きく混乱させます。

「ABC」の後のバイトがスペースまたはヌル文字である場合、より大きな置換データを書き込んでも問題が発生しない可能性が高くなります。 ABC {whatever_follows_it}をWXYZに置き換える必要があります。そのため、データをバイトのままにして、置換データを一度に1バイトずつ書き込む方が簡単であることがわかるでしょう。

7
J.Merrill

.NET文字列はUnicode文字列を使用するため、Cで行ったようにこれを行うことはできません。ほとんどの場合、attemptで往復することはできません内容が実際にtextでない限り、string <-> byte配列から。

この点を明確にする必要があります:.NETでは、byte[]データがtextではないため、バイナリデータ用の特別な Base64 エンコーディングを除いて、stringに変換しないでください。テキストチャネルを介して。これは、.NETで作業する人々の間で広く認識されている誤解です。

5
Sam Harwell

あなたの問題はあなたがバイトの配列を比較している方法であるように見えるでしょう:

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

含まれている値ではなく、バイト配列のアドレスを比較しているため、これは常にfalseを返します。文字列データを比較するか、バイト配列を比較する方法を使用します。代わりにこれを行うこともできます:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes));
3
csharptest.net