プロが教えるわが家の防犯対策術!

Javaで日本語1文字のバイト数はいくつになるのでしょうか。
単純に2バイトではないような書き込みを見たことがあるのですが本当でしょうか。
2バイト以外は特殊な文字で「あいうえお山川」のような通常使う文字が2バイト
ということでしょうか。
また、C言語(C#も含む?)であれば全角は2バイト、半角は1バイトで計算できると
いうのは本当でしょうか。

A 回答 (7件)

ここらへんの話を全部説明しようとすると、エンコーディング(Encoding)、キャラクターセット(Encoded Character Set)、フォント(Font)、グリフ(Glyph)とはなんぞやというところまで言及しないといけなくなって、内容的に一冊の本くらいのボリュームになるため、色々な資料を探して目を通して欲しい。



簡単な解説
エンコーディング:どの文字にどの番号を与えるかを取り決めたもの。UTF-8やEUC-JPなど。
キャラクターセット:どの文字を扱うかを取り決めたもの。JIS X 0213やUNICODE 4.0など。
フォント:字体、書体と訳される。文字の形の内、人間が「あ」なら「あ」と文字を識別するんだけど、とめはねがあったりなかったりするもの。明朝体・ゴシック体やセリフ体・サンセリフ体など。
グリフ:字形。葛飾区の葛の左下がヒだったり人と縦棒と横棒だったり、識別される文字としては同じ葛なんだけど、形が違うもの。例に出した葛は、NECのFA明朝(JIS78版)とMS明朝では、同じコードポイントでFA明朝は人と縦棒と横棒であり、MS明朝ではヒになっている。UNICODEの世界においてもバリエーションセレクターという概念が導入されて、同じコードポイントでグリフが違うものを表現できる仕組みになっている(にも関わらず鴎(かもめ)とメが口3つになったものはグリフが違うだけなのに別のコードポイントが割り当てられているなど対応に全く統一性がないので混乱しちゃう)。

さて、今までで○○は△△だ、いやそうじゃないと色々議論されている中で正確なところをまとめてみたい。質問者が混乱しそうなポイントに絞って説明する。

・UTF-8は1文字が4バイトまでではなく6バイトまでが正しい。
 サロゲートペアを32ビットの状態でUTF-8符号化を行った場合に最大で6バイトになる。のだが、Javaには関係ないお話。詳細は後述。

・「Javaの内部文字コードはUTF-16」は半分誤り。
 何を以て「内部文字コード」と表現するかにもよるのだが、物理的には変則的なUTF-8で物理メモリ上に格納されているので物理的にはUTF-16ではない。
 論理的には、(サロゲートペアやバリエーションセレクターは例外として)Javaにおける1文字とは1つのcharに代入できる値の範囲であり、格納される各文字に割り当てられた値はUTF-16と完全に一致する。
 変則的なUTF-8と言ったのは、サロゲートペアはUTF-8では前述の通り32ビットのコードポイントが1バイトから6バイトに符号化されるのだが、Javaでは上位サロゲートと下位サロゲートそれぞれ16ビットを1バイト~3バイトに符号化して格納している。これはサロゲートペアが導入されたJava5(1.5.0)の時点でのお話なので、今(Java1.7や1.8)では事情は違うかもしれない。

・EUC-JPは半角は1バイト、全角は2バイトは誤り。
EUC-JPはキャラクターセットとしてJIS X 0201、JIS X 0208、JIS X 0212の合同集合を扱う事ができるエンコーディング方式なのだが、JIS X 0201のカナ部分は1バイトではなく3バイトで符号化される。つまりEUC-JPでも2バイトを超える文字があるのだ。
ところで、質問にある「C言語であれば全角は2バイト、半角は1バイト」という話があるが、これは日本のプログラマーにとって身近だったMS-DOS(R) 日本語版でMS-CやBorland-C++にて開発する時、あるいはMS-Windows(R) 日本語版でVisual C++で開発する時に、何も特別な事をしないでファイルを読み書きするとShiftJIS(正確にはWindows-31J)で読み書きされていた事に起因すると私は思う。根本的に誤った概念なので忘れた方が良いだろう。

さて、今まではJavaの中で文字列(charやStringクラス)を扱う時のお話をしてきたが、ここでOutputStreamWriterで文字をストリームに書き込む時のお話をしてみよう。
OutputStreamWriterをエンコーディングを指定せずにインスタンス化した時、Javaが勝手にエンコーディングを決めているだけであり、これで例えばそこからFileOutputStreamを経て書き出されたファイルの中身がンバイトだったらかJava内部ではンバイトで格納されているという議論は全く意味をなさない。
この辺はOutputStreamWriterについて詳しく調べてみるといいだろう。

つまり、質問内容に対する回答は、状況によって変わるという訳だ。
Javaが内部で保持しているコードポイントはどの値をどの文字として扱っているかと言えばそれはUTF-16、それを物理的にメモリダンプしたらどうなっているかと言えばそれは変則的なUTF-8チックのエンコーディング方式、ファイルやソケットごしにどうなっているかと言えばそれはエンコードをきちっと指定して使いなさい(それで指定したエンコードでは文字コードの範囲がどうなっているか確認しなさい)という事。
    • good
    • 0

Java にて文字のバイト数は、昔なら2バイト固定だったのですが、最近は「不定」です。


これは Unicode の仕様拡張に由来しているため、Unicode を採用したプログラム言語すべてに共通する特徴になります。


Java 内部処理では char は UTF-16 で扱うので 1単位=2byte
ASCII や JIS カナ(いわゆる半角文字)も1単位

通常の文字は 1文字=1単位=2byte
JIS90範囲内(いわゆる全角文字)ならほぼすべてこれ

一部の文字はサロゲートペアのため 1文字=2単位=4byte
JIS2004の一部が該当
例: U+2000B → 「\uD840\uDC0B」

Unicode正規化で分解されると、結合文字は 1文字=2単位=4byte
Macのファイルシステム関連だとこうなるらしい
例: 「が」→「\u304B\u3099」

アイヌ語表音記号の様にUnicodeに定義が無いなら、正規化されなくとも 1文字=2単位=4byte
JIS2004の一部が該当
例: 「半濁点付き平仮名か」→「\u304B\u309A」

正規化で互換分解までされると、1文字=n単位(n=1..上限未定)
例: 「ローマ数字8」→「\u0076\u0069\u0069\u0069」

上記の特殊ルールを全て加味して文字列のサイズ計算を行うならば、
「バイト数」を知りたいならば String#length に×2
「文字数」を知りたいなら Normalizer してから String#codePointCount

--

内部にシフトJIS/EUCを使っているプログラム言語の場合や、Java の入出力で UTF-8 を使う場合などは、説明が長くなるので割愛させていただきます。
    • good
    • 0

文字コードに絡む「UTF」には複数の意味がありますが, どの意味においても「UTF-8 は 4バイト (『4オクテット』というべき?) まで」のはずです>#2.



ただし「1つのコードポイントがたかだか 4バイト」と言っているにすぎず, #3 に現れる結合文字や異体字セレクタなんかを使いだすと「1文字」のバイト数はもっと増やすことができます (異体字セレクタは 1つしかつけられないが, 理論上結合文字はいくつでもつなげられるので).
    • good
    • 0

Javaに関してはこの辺を読まれるとよいかもです。


http://docs.oracle.com/javase/jp/6/api/java/lang …

また#3の方が既におっしゃっていますが全角半角というのはフォントの話であって、1文字が何バイトなのかとは関係ありません。
    • good
    • 0

JavaやC#(というか.NET Framework)は文字列型の内部コードがUTF-16なので,日本語というか,全ての文字の処理単位が16ビットです。


サロゲートや結合文字,異体字セレクタなどがあるので,1文字が16ビットというわけではありませんが。
例えば,
    • good
    • 0

どんなデータ形で記憶するのか、どの文字コード系を採用したかによります。


Stringやchar[]では、 1文字は16bitです。

String.GetByte()等でbyte[]に記憶する場合は、その文字コード次第です。
SHift_JIS,EUC-JPでは、いわゆる「全角文字」は2バイトです。
UTF-8は1~6バイトです。日本語で使われる文字は、大体3バイトです。


C言語でも事情は同じようなものです。
「全角は2バイト、半角は1バイト」というのは、UTF-8が普及するまではShift_JISやEUC-JPが一般的だったため、そうだと決めつけてしまっているだけです。(特に古い入門書等)
    • good
    • 0

Javaはunicodeを扱うので2バイトです。



2バイトは2の16乗の数が扱えるので、65536個の文字種が理論上表現できます。 基本的に世界中の文字が含まれますが、日本語の漢字と中国語の漢字の字体がまったく同じ場合は、両者は共用されます。

国際規格なので、全ての日本語漢字が含まれているわけではないです。 難読字など存在しないものは、外字で表現するしか方法がないはずです。 外字とはUnicodeの空きエリアを使って、独自に文字をデザインしそれと文字コードが対応するようにしたものです。 当然、フォントデザインがないコンピュータでは、互換性はありません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!