質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

1回答

1868閲覧

文字列からバイトへの変換がうまく行かない

yukkuri

総合スコア624

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2019/01/21 12:40

編集2019/01/21 12:42

現在、文字コードの変換について行っていて、文字列をバイトに変換する、というのがありました。

package org.jyl.base.io; import java.util.ArrayList; import javax.xml.bind.DatatypeConverter; /** * Java のプリミティブ型 {@code char} を基に、 * 複数文字コードに対応した単一文字を示すクラスです。 * このクラスでは、Java の仕様上、文字コードとバイトを用いて * 文字を特定したあと、{@code UTF-16} に変換されます。 * * @author とあるゆっくり */ public class JylChar { // 文字コードごとに変換後の対応する char 値 private final char c; // 文字コード private final CharCode code; // 文字を対応する文字コードに変換した際のバイト private final ArrayList<Byte> charbyte = new ArrayList<Byte>( 0 ); /** * オブジェクトに文字とエンコードを格納します。 * * @param c 文字 * @param code エンコードの列挙 */ public JylChar( char c, CharCode code ) { // 文字をセット this.c = c; // 文字コードを指定 this.code = code; setByte( this.c ); } /** * バイトと文字エンコードから文字を取得します。 * * @param b 一文字のバイト この中の全てのバイトを用いて文字を決定します。 * ただし、エンコードごとに決められたサイズを超えた場合、切り捨てされることがあります。 * @param code 文字のエンコード * * @throws IllegalArgumentException 指定エンコードと指定バイトで文字が決定しなかった場合 */ public JylChar( byte[] b, CharCode code ) { // 文字コードを設定 this.code = code; int loop = 0; // 1 文字のバイト数( 最大 ) if( code == CharCode.ASCII ) loop = 1; if( code == CharCode.EUC ) loop = 3; if( code == CharCode.Shift_JIS ) loop = 2; if( code == CharCode.Unicode ) loop = 4; if( code == CharCode.UTF_8 ) loop = 6; if( b.length > loop ){ // 文字を指定するのに必要なバイト数をオーバーした場合 byte[] bys = new byte[ loop ]; // オーバーしたデータを入れられた場合、計算に使われる配列 for( int l = 0; l < bys.length; l++ ) bys[ l ] = b[ l ]; // バイトと文字エンコードから文字を取得 c = setChar( bys ); }else{ c = setChar( b ); } setByte( c ); } /** * 指定したエンコードで指定した文字を出力するためのバイト配列を返します。 * * @return 指定文字を示すバイト配列 */ public byte[] getBytes() { // 必要数のバイト配列を作成 byte[] by = new byte[ charbyte.size() ]; for( int l = 0; l < charbyte.size(); l++ ){ by[ l ] = charbyte.get( l ); } return by; } /** * このクラスに格納されている文字を取得します。 * * @return 格納されている文字 エンコードなどによっては機種依存文字などが含まれる可能性があります。 */ public char getChar() { return c; } /** * この文字の文字コードを返します。 * なお、文字コードを変更することはできません。 * * @return このオブジェクトの文字コード */ public CharCode getCharCode() { return code; } // private のメゾッド( 公開する必要がない ) 公開するとデータを壊す可能性があるため // バイトをセットする private void setByte( char c ) { String binarydata = ""; // バイトに変換した際のデータを入れる 16 進数データ switch( c ){ case '0':{ if( code == CharCode.ASCII ) binarydata = "30"; if( code == CharCode.EUC ) binarydata = "A3B0"; if( code == CharCode.Shift_JIS ) binarydata = "824F"; if( code == CharCode.UTF_8 ) binarydata = "EFBC90"; if( code == CharCode.Unicode ) binarydata = "FF10"; break; }case '1':{ if( code == CharCode.ASCII ) binarydata = "31"; if( code == CharCode.EUC ) binarydata = "A3B1"; if( code == CharCode.Shift_JIS ) binarydata = "8250"; if( code == CharCode.UTF_8 ) binarydata = "EFBC91"; if( code == CharCode.Unicode ) binarydata = "FF11"; break; } } // binarydata の文字列を 16 進数に変換 byte[] bytes = new byte[ binarydata.length() / 2 ]; for( int l = 0; l < bytes.length; l++ ){ // バイト値 一旦保存用 byte bycp = (byte)Integer.parseInt( binarydata.substring( l * 2, ( l + 1 ) * 2 ), 16 ); bytes[ l ] = (byte)( ~bycp + 1 ); } // 全てのバイトを charbyte に追加 for( int l = 0; l < bytes.length; l++ ){ charbyte.add( bytes[ l ] ); System.out.println( "b" + bytes[ l ] ); } } // バイト配列から char を取得します。 // 引数から生成できない場合例外 private char setChar( byte[] b ) { String bdata = DatatypeConverter.printHexBinary( b ); System.out.println( bdata ); if( code == CharCode.UTF_8 ){ switch( bdata ){ case "EFBC90": return '0'; case "EFBC91": return '1'; } throw new IllegalArgumentException(); } }

上のソースのコンストラクタでバイトを指定して、バイトに{ 0xEF, 0xBC, 0x92 }のデータ、UTF-8というデータを与えました。そしたら、
1 を入力した、というデータは取得できたのですが、コンストラクタで呼び出しているsetByteで正しいバイトが入っていないようでした。
その当時は-の値だったので、ネットで調べ、整数値を出すことに成功しました。
しかし、現在出力されている値は 1 つめが 17 です。ただ、0xEFは 10 進数に直すと 239 なので、正しい値が入っていないようです。
// binarydata の文字列を 16 進数に変換のところでエラーが起きていると思われるのですが... どうしたらいいでしょうか。

package org.jyl.base.io; /** * 文字コードを定義した列挙型です。 * * @author とあるゆっくり */ public enum CharCode { /** * {@code ASCII} を示します。 * 最大バイト数は 1 バイトです。 */ ASCII, /** * {@code EUC-jp} を示します。 * 半角カタカナの対応予定は現在ありません。 * 最大バイト数は制御文字も合わせ 3 バイトです。 */ EUC, /** * {@code Shift-JIS} を示します。 * 最大バイト数は 2 バイトです。 */ Shift_JIS, /** * {@code Unicode}( UTF-16 ) を示します。 * {@code UTF-8} は {@code UTF_8} を参照してください。 * 最大バイト数は 4 バイトです。 */ Unicode, /** * {@code UTF-8} を示します。 * 技術的制限により、_を使用しています。 * 最大バイト数は 6 バイトです。 */ UTF_8, };

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

0xEF は int として見ると 239 かもしれませんが, (signed) byte としてみると -16 です.

(byte)( ~bycp + 1 );

の結果は 17 ですので, 「現在出力されている値は 1 つめが 17 」というのはコードの動きとしては合っていると思います.
この変換を外しては如何でしょうか.

つまり「その当時は-の値だった」のが正しく, 「整数値を出すことに成功」したのは byte が signed(値範囲:-128~127) ではなく unsigned (値範囲:0~255) と思われていた勘違いからのコードの破壊だったと思います.

投稿2019/01/21 16:17

編集2019/01/22 08:35
jimbe

総合スコア12543

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukkuri

2019/01/22 10:13

そういうことだったんですね。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問