30

ファイルにバイナリデータがあり、バイト配列に読み込んで問題なく処理できます。ここで、ネットワーク接続を介してデータの一部を XML ドキュメントの要素として送信する必要があります。私の問題は、データをバイト配列から文字列に変換してバイト配列に戻すと、データが破損することです。これを 1 台のマシンでテストして、問題を文字列変換に切り分けたところ、XML パーサーやネットワーク トランスポートによって破損していないことがわかりました。

私が今持っているのは

byte[] buffer = ...; // read from file
// a few lines that prove I can process the data successfully
String element = new String(buffer);
byte[] newBuffer = element.getBytes();
// a few lines that try to process newBuffer and fail because it is not the same data anymore

バイナリを文字列に変換し、データを失うことなく元に戻す方法を知っている人はいますか?

回答済み: ありがとう、サム。私はばかのように感じます。私のSAXパーサーが文句を言っていたので、昨日これに答えてもらいました。この一見別の問題に遭遇したとき、何らかの理由で、それが同じ問題の新しい症状であるとは思いもしませんでした。

編集: 完全を期すために、 Apache Commons CodecパッケージのBase64クラスを使用してこの問題を解決しました。

4

4 に答える 4

36

String(byte[])は、データをデフォルトの文字エンコーディングとして扱います。したがって、バイトが 8 ビット値から 16 ビット Java Unicode 文字に変換される方法は、オペレーティング システム間で異なるだけでなく、同じマシンで異なるコードページを使用している異なるユーザー間でも異なる可能性があります! このコンストラクターは、独自のテキスト ファイルの 1 つをデコードする場合にのみ適しています。Java で任意のバイトを char に変換しようとしないでください。

base64としてエンコードすることは良い解決策です。これは、ファイルが SMTP (電子メール) 経由で送信される方法です。(無料の) Apache Commons Codecプロジェクトがその役割を果たします。

byte[] bytes = loadFile(file);          
//all chars in encoded are guaranteed to be 7-bit ASCII
byte[] encoded = Base64.encodeBase64(bytes);
String printMe = new String(encoded, "US-ASCII");
System.out.println(printMe);
byte[] decoded = Base64.decodeBase64(encoded);

または、Java 6 DatatypeConverterを使用できます。

import java.io.*;
import java.nio.channels.*;
import javax.xml.bind.DatatypeConverter;

public class EncodeDecode {    
  public static void main(String[] args) throws Exception {
    File file = new File("/bin/ls");
    byte[] bytes = loadFile(file, new ByteArrayOutputStream()).toByteArray();
    String encoded = DatatypeConverter.printBase64Binary(bytes);
    System.out.println(encoded);
    byte[] decoded = DatatypeConverter.parseBase64Binary(encoded);
    // check
    for (int i = 0; i < bytes.length; i++) {
      assert bytes[i] == decoded[i];
    }
  }

  private static <T extends OutputStream> T loadFile(File file, T out)
                                                       throws IOException {
    FileChannel in = new FileInputStream(file).getChannel();
    try {
      assert in.size() == in.transferTo(0, in.size(), Channels.newChannel(out));
      return out;
    } finally {
      in.close();
    }
  }
}
于 2008-08-21T19:19:30.153 に答える
21

base64 でエンコードすると、すべてのデータが ASCII セーフ テキストに変換されますが、base64 でエンコードされたデータは元のデータよりも大きくなります。

于 2008-08-21T18:54:06.487 に答える
2

この質問を参照してください。バイナリ データを XML に埋め込むにはどうすればよいですか? byte[] を String に変換してから XML のどこかにプッシュする代わりに、base64 エンコーディングを介して byte[] を String に変換します (一部の XML ライブラリには、これを行うための型があります)。XML から文字列を取得したら、BASE64 でデコードします。

http://commons.apache.org/codec/を使用

あらゆる種類の奇妙な文字セットの制限と非印刷文字の存在により、データがめちゃくちゃになっている可能性があります。BASE64で貼り付けます。

于 2008-08-21T19:13:56.593 に答える
0

XML ドキュメントをどのように作成していますか? Java のビルトイン XML クラスを使用する場合は、文字列エンコーディングを処理する必要があります。

javax.xml および org.xml パッケージを見てください。これは、XML ドキュメントの生成に使用するものであり、すべての文字列のエンコードとデコードを非常にうまく処理します。

- -編集:

うーん、私は問題を誤解したと思います。通常の文字列をエンコードしようとしているのではなく、任意のバイナリ データのセットをエンコードしようとしていますか? その場合、以前のコメントで提案された Base64 エンコーディングがおそらく最適な方法です。これは、XML でバイナリ データをエンコードするかなり標準的な方法だと思います。

于 2008-08-21T19:10:31.127 に答える