2017-02-03 6 views
3

10進数をasciiに変換したいのですが、これは予期しない結果を返すコードです。ここに私が使用しているコードがあります。文字セットを指定した場合、どの文字コードを `char`に変換するのですか?

public static void main(String[] args) { 
    char ret= (char)146; 
    System.out.println(ret);// returns nothing. 

は私がhttp://www.ascii-code.com/ 誰でもあたりとして「'」単一の文字を取得するには、この出くわした期待しますか?ありがとう。

+4

"拡張ASCII"は誤った名前です。 ASCIIの定義は127までです。その範囲を拡張する文字セットがありますが、それらがどのようにするかは大きく異なります。だからあなたは本当にあなたが話していることを知る必要があります。あなたのコードでやっていることは、幸いなことに、一重引用符と一致するUnicodeコードポイント146を印刷しています:http://www.fileformat.info/info/unicode/char/92/index.htm –

+0

おそらくあなたの答えはここにあります:http://stackoverflow.com/questions/13012871/converting-ascii-code-to-char-in-java –

+0

私の入力には127より大きい小数点があります。いくつかは正しく変換されますが、 '146'のようなものは問題を引き起こします。 – Paresh

答えて

6

だから、いくつかのことがあります。

あなたがにリンクされているすべてのページの最初の質問のコード・ポイントの範囲については、これを言う:

拡張ASCIIコード(文字コード128-255)

いくつかの異なるバリエーションがあります。 8ビットASCIIテーブルの下記の表は、ISO 8859-1(ISO Latin-1とも呼ばれる)に準拠しています。コード128-159には、Microsoft®Windows Latin-1拡張文字が含まれています。

これは間違っているか、少なくとも私にとって誤解を招く言葉です。 ISO 8859-1/Latin-1 does not define code point 146(およびanother reference just because。だからすでに問題を抱えています。

String s = new String(new byte[] {(byte)146}, "iso-8859-1"); 
System.out.println(s); 

出力と同じ「予想外」の結果を:あなたはStringて変換を行う場合にも、これを見ることができます。 実際に何を参照しているのかは、Windows-1252セット(別名「Windows Latin-1」ですが、この名前はほとんど完全に時代遅れです)、コードポイントを右の一重引用符(他の文字セットそれは)this listを参照し、0x92でそれを提供エンコーディングを探して146でこの文字を提供し、我々のようなこれを確認することができます

String s = new String(new byte[] {(byte)146}, "windows-1252"); 
System.out.println(s); 

だから、最初の間違いは、ページが混乱しているということです。

しかし、大きな間違いは、あなたがやっているやり方でやろうとしていることをすることができないことです。 Javaでのcharは、UTF-16コードポイント(またはその半分、補助文字> 0xFFFFを表す場合は、charはBMPポイントに対応し、その1つはintです)補足物を含む)。

残念ながら、Javaでは実際には1文字の変換で多くのAPIが公開されていません。 Characterでも、選択した文字セットからUTF-16に変換する方法はありません。

したがって、1つのオプションは、上記の例でヒントとしてStringを使用して行います。生byte[]配列としてあなたのコードポイントを表現し、そこから変換:

String s = new String(new byte[] {(byte)146}, "windows-1252"); 
System.out.println(s); 
char c = s.charAt(0); 
System.out.println(c); 

あなたはs.charAt(0)を経由して再びcharをつかむことができました。これを行うときは、キャラクタセットに注意する必要があることに注意してください。ここでは、バイトシーケンスが指定されたエンコーディングに対して有効であることを知り、その結果が1つだけcharであることがわかっているので、これを行うことができます。

しかし、一般的な場合は注意が必要です。たとえば、バイトシーケンスと文字セットによって、UTF-16補助文字の範囲にある結果が得られる可能性があります。その場合、s.charAt(0)は十分でなく、intに格納されているs.codePointAt(0)が代わりに必要となります。それは、同じように不格好だが、代替案として

、同じ警告で、あなたは、デコードする Charsetを使用することができます例えば:私は Charset#decodeは、「補助文字を処理し、できるか全くわからない

Charset cs = Charset.forName("windows-1252"); 
CharBuffer cb = cs.decode(ByteBuffer.wrap(new byte[] {(byte)146})); 
char c = cb.get(0); 
System.out.println(c); 

注意今は本当にテストしています(でも誰でも自由にチャイムしてください)。余談として


:あなたのケースでは、146(0x92)がcharに直接キャストは、UTF-16文字の「PRIVATE使用する2つの」(see also)に対応し、全てのベットは、あなたが終わるだろう何のためにオフになっていますそこに表示されます。この文字はclassified by Unicode as a control characterで、ANSI端末制御のために予約されている文字の範囲に含まれているようです(AFAIKは実際には使用されませんが、その範囲にかかわらず)。おそらく、一部のロケールのブラウザで互換性のための一重引用符としてレンダリングされているのであれば、私は驚くことはありませんが、端末はそれに奇妙なことをしました。

また、fyiは、right single quote is 0x2019の公式のUTF-16コードポイントです。あなたは確実にその値を使用してcharにそれを格納することができ、例えば:

ます。また-1252窓からの変換後の値を見て、自分のためにこれを見ることができます
System.out.println((char)0x2019); 

String s = new String(new byte[] {(byte)146}, "windows-1252"); 
char c = s.charAt(0); 
System.out.printf("0x%x\n", (int)c); // outputs 0x2019 

しますか、完全性のために:

String s = new String(new byte[] {(byte)146}, "windows-1252"); 
int cp = s.codePointAt(0); 
System.out.printf("0x%x\n", cp); // outputs 0x2019 
+0

この有益な記事を読むと、なぜその言語が(char)型キャストを許可するのか、もしそうであれば、なぜエンコーディングを指定する必要がないのか、たとえば、(char:cp1252)integer_variableなどです。何十ものシングルバイトエンコーディングスキームがあります:https://en.wikipedia.org/wiki/Windows_code_page –

+0

@Thomasそうではない理由がないのでキャストが可能ですし、特殊な特殊ケースにする必要があります他のすべてのケースで互換性のある型間のキャストが許可されているためです。それは不必要に制限され、特別なケースのコンパイラエラーを実装することになります。 –

+0

2番目の質問については、エンコーディングが暗示されています。charはUTF-16です。期間。もしあなたがエンコーディングを指定し、コンパイラがあなたのためのCharset検索でそれをラップすることができれば、それは*便利です*しかし、それは砂糖だけだろう。また、Charset.forNameがスローできる例外を処理する必要があるキャストもあります(https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html#forName(java)。 lang.String))。また、私は、単一の文字エンコーディングが比較的まれなユースケースであるという気持ちがあるので、ここで弱いAPIです。私はむしろ文字セット名を取るCharacterコンストラクタを見るでしょう。 –

0

参照するページには、160〜255の値がISO-8859-1(別名Latin 1)テーブルに対応しています。 128から159の範囲の値は、Windows固有のLatin 1(ISO-8859-1の範囲は未定義で、オペレーティングシステムによって割り当てられる)のものです。

Java文字はUTF16に基づいており、それ自体はUnicodeテーブルに基づいています。適切な引用符文字を特に参照したい場合は、Javaで'\u2019'と指定することができます(http://www.fileformat.info/info/unicode/char/2019/index.htmを参照)。

関連する問題