10

ヘイホー、

何でもよいバイトデータを文字列に変換したい。私の質問は、たとえばUTF-8でバイトデータをエンコードすることが「安全」かどうかです。

String s1 = new String(data, "UTF-8");

またはbase64を使用して:

String s2 = Base64.encodeToString(data, false); //migbase64

最初の方法を使用すると、マイナスの副作用があるのではないかと心配しています。つまり、両方のバリアントが p—e—r—f—e—c—t—l—y— で機能しますが、s1には UTF-8 文字セットの任意の文字を含めることができ、s2は「読み取り可能な」文字のみを使用します。本当にbase64を使用する必要があるかどうかはわかりません。基本的には、文字列を作成してネットワーク経由で送信し、再度受信するだけです。(私の状況では他に方法はありません:/)

問題は、それが可能かどうかではなく、負の副作用についてのみです!

4

3 に答える 3

23

base64 または場合によっては 16 進数を絶対に使用する必要があります。(どちらでも動作します。base64 はよりコンパクトですが、人間が読み取るのは困難です。)

「両方のバリアントが完全に機能する」と主張していますが、実際にはそうではありません。最初のアプローチを使用し、data実際には有効な UTF-8 シーケンスでない場合、データが失われます。UTF-8 でエンコードされたテキストを に変換しようとしているわけStringではないので、そうしようとするコードを書かないでください。

エンコーディングとして使用ISO-8859-1すると、すべてのデータが保持されますが、多くの場合、返される文字列は他のプロトコル間で簡単に転送されません。たとえば、印刷できない制御文字が含まれている可能性があります。

コンストラクターは、たまたまエンコードされた形式 (エンコーディングが 2 番目の引数として指定されている) である、本質的にテキストString(byte[], String)データを取得している場合にのみ使用してください。音楽、ビデオ、画像、暗号化または圧縮されたデータなど、それ以外の場合は、着信データを「任意のバイナリデータ」として扱い、そのテキストエンコーディングを見つけるアプローチを使用する必要があります...これはまさにbase64そして16進法。

于 2013-11-10T20:26:03.193 に答える
6

良い考えではありませんが、文字列にバイトを格納できます。これはバイトを管理するため、UTF-8 を使用することはできませんが、ISO-8859-1 エンコーディングまたはプレーン 8 ビットを使用する方が高速で効率的です。これを行う最も簡単な方法は、

String s1 = new String(data, 0);

また

String s1 = new String(data, "ISO-8859-1");

ウィキペディアの UTF-8から、Jon Skeet が指摘しているように、これらのエンコーディングは標準では有効ではありません。Java での動作はさまざまです。DataInputStream は、最初の 3 つのバージョンを同じものとして扱い、次の 2 つのバージョンは例外をスローします。Charset デコーダーは、それらを個別の文字として静かに扱います。

00000000 is \0
11000000 10000000 is \0
11100000 10000000 10000000 is \0
11110000 10000000 10000000 10000000 is \0
11111000 10000000 10000000 10000000 10000000 is \0
11111100 10000000 10000000 10000000 10000000 10000000 is \0

これは、文字列に \0 が表示された場合、元の byte[] 値が何であったかを確実に知る方法がないことを意味します。DataOutputStream は、\0 をターミネータと見なす C との互換性のために 2 番目のオプションを使用します。

ところで DataOutputStream はコード ポイントを認識しないため、上位コード ポイントの文字を UTF-16 で書き込み、次に UTF-8 エンコードで書き込みます。

0xFE および 0xFF を文字に使用することはできません。値 0x11000000+ は、マルチバイト文字内ではなく、文字の先頭にのみ表示できます。

于 2013-11-10T20:28:12.400 に答える