技術とか戦略とか

SIerで証券レガシーシステムを8年いじってからSESに転職した業務系エンジニアによる技術ブログ。

文字コードの入門

この記事では、文字コードに関する初歩的な内容について簡単に書きます。
 
1.文字コードという概念とコード体系
コンピューターで取り扱う文字には、それぞれコードが割り振られています。
コードは1~4バイトの情報として取り扱われ、1バイトの文字は1バイト文字、2~4バイトの文字はマルチバイト文字と呼ばれます。
原則として、半角英数字記号は1バイト文字として扱われ、それ以外の文字はマルチバイト文字として扱われます。
(ここでは詳しく触れませんが、半角カナや人間には読めない制御文字は、1バイト文字のこともあればマルチバイト文字のこともあります)
これらの情報は、16進数で表現されることが多いです。また、プログラム上では、10進数で表現されることも多いです。
 
どの文字にどのコードが割り振られるのかは、コード体系によって決まります。
 
1バイト文字に関しては、今日のPCではASCIIというコード体系が使われます。
ASCIIにて、どの文字にどのコードが割り振られているのかは、以下の表から確認することができます。
(例えば、「A」には「0x41」(10進数で「65」)が、「a」には「0x61」(10進数で「97」)が割り振られています)

https://ja.wikipedia.org/wiki/ASCII

 
また、ホストコンピューターでは、1バイト文字にEBCDICという別のコード体系が使われます。
EBCDICの表は以下の通りであり、ASCIIとは異なる割り振られ方をしていることがわかります。
(例えば、「A」には「0xC1」(10進数で「193」)が割り振られています)

https://ja.wikipedia.org/wiki/EBCDIC

 
マルチバイト文字については、今日ではUTF-8やShiftJISといったコード体系が使われることが多いです。
(マルチバイト文字に関しては、この記事では詳細を割愛します)
 
2.ソースコード上で文字コードを取り扱う例
ソースコード上でも、文字コードを取り扱うことができます。
と言うより、文字は内部的には文字コードであり、「A」や「a」といった表示は人間が読みやすいように表現しているものです。
 
以下は、「A」や「a」といった文字が内部的にどのような文字コードを持っているのかを表示するJavaのプログラムです。
ASCIIコード表通りの文字コードが割り振られていることを確認できます。
 
ソースコード
・CharCode1.java
public class CharCode1 {

    public static void main(String args) {

        // 「A」を文字コードとして表現
        String char_A = "A"; // 文字列"A"を定義
        short code_A = (short)char_A.charAt(0); // 文字列"A"を文字コードに変換
        System.out.println("「" + char_A + "」の文字コード:" + code_A); // 表示

        // 「a」を文字コードとして表現
        String char_a = "a"; // 文字列"a"を定義
        short code_a = (short)char_a.charAt(0); // 文字列"a"を文字コードに変換
        System.out.println("「" + char_a + "」の文字コード:" + code_a); // 表示

    }

}
 
■実行結果
「A」の文字コード:65
「a」の文字コード:97
 
また、文字の比較も、文字コードにより行うことができます。
以下は、「ABC」という文字列を前から1文字ずつ読み込み、「B」の文字を読みこんだ時だけ表示を行うJavaのプログラムです。
 
ソースコード
・CharCode2.java
public class CharCode2 {

    public static void main(String args) {

        // 文字列「ABC」を1文字ずつ読込
        String str = "ABC"; // 文字列"ABC"を定義
        for (int i = 0; i < str.length() ; i++) { // 1文字ずつループ
            short code = (short)str.charAt(i); // 読み込んだ文字の文字コード取得
            if (code == 66) { // 文字コードが66("B")の場合
            // if (str.substring(i, i+1).equals("B")) { // このように書いても同じ
                System.out.println((i + 1) + "番目の文字:" +
                    str.charAt(i) + " 文字コード:" + code);
            }
        }
    }

}
 
■実行結果
2番目の文字:B 文字コード:66
 
3.文字コードを意識する理由
ここで、「なぜプログラミングで文字コードを意識する必要があるのか」と疑問を持った方もいらっしゃるかもしれません。
確かに、人間には読みにくい文字コードを使ったプログラミングをするよりも、文字を直接使ったプログラミングの方が望ましいように思えます。
例えば、この記事で2つ目に取り上げたソースコード(CharCode2.java)では、文字コードを使用しなくても文字コードを使った時のような制御を実現でき、それならば文字コードを使った制御をしない方が望ましいように思えます。
 
それでも文字コードを意識する一番の理由は、バイナリの制御文字を取り扱うために必要だからです。
文字には、人間が読める文字の他に、コンピューターに命令を送るための制御文字が存在します。
多くの人にとって一番馴染みがある制御文字の一つが「改行文字」です。
コンピューターが改行文字を読みこむと、文章の改行が行われます。
(この記事が正しく改行されて読みやすくなっているのも、この「改行文字」のおかげです)
改行文字はOSによって割り振られている文字コードが異なりますが、Unix/Linuxの場合は「10」が割り振られています。
この文字は、プログラム上で"A"や"a"といった形で記述することができず、プログラミング言語やライブラリでサポートされない場合は、文字コードを参照しないと改行文字であるか否かを判定できません。
 
例えば、Javaで絵文字を含む文字列を1文字ずつ切り取る場合に、文字コードの参照が必要になります。
解説やコード例は以下の記事に書いています。
java:Unicodeの絵文字をjavaで取り扱う
 
文字コードについてプログラミングの入門書に書かれていることは少ないですが、実務では度々目にします。
実務でプログラミングをするのであれば、文字コードについても早めに勉強しておくことをお勧めします。