Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【社内勉強会】Web開発者に知ってほしい「文字コード」の話(2017/04/19)

More than 3 years have passed since last update.

【社内勉強会】Web開発者に知ってほしい「文字コード」の話(2017/04/19)

by yuji38kwmt
1 / 38

0. はじめに


対象者

  • Webシステムを開発している人
    • Java Servlet
    • HTML5

伝えたいこと

  • 文字コードの概要
  • 文字コードの指定箇所
  • 1文字なのに2文字と認識される場合がある

参考図書

プログラマのための文字コード技術入門

参考図書.jpg

このスライドでは、この本の文章や図を引用している。


目次

  1. 文字コードの概要
    • 代表的な文字コードの特徴
    • ASCIIとASCII互換の文字コード
    • UTF-8を推奨
    • 文字コードの自動判別
  2. Webシステムにおける文字コードの指定個所
  3. 付録

1. 代表的な文字コードの特徴


文字コードとは?

文字集合を定義し、その集合の各文字に対応するビット組み合わせを一意に定めたものが文字コードです。

参考図書より引用

たとえば、「[A]という文字は[1000001]というビット組み合わせにする」というルールのこと。


代表的な文字コード

  • Shift_JIS
  • EUC-JP
  • UTF-8

EUC-JP

日本語を表現する文字コードの一つ。
Extended UNIX Code Packed Format for Japanese の略。
Unix系OSで広く使われている。
1985年にAT&T社が定めた。

最大2バイト。

最近のUnix系OSのデフォルト文字コードはUTF-8。


Shift_JIS

日本語を表現する文字コードの一つ。
1982年に誕生した。

各ベンダーの亜種が存在する。
(「Windows-31J」など。波ダッシュ問題の原因。後述参照)

最大2バイト。


UTF-8

世界中の文字を扱えるようにした「Unicode」という文字集合を、8bit単位で表現した文字コード。
たとえば、アクセント記号([é])はShift_JISでは表現できないが、UTF-8ならば表現できる。

Unicodeは1993年制定された。
“UCS Transformation Format 8”、または “Unicode Transformation Format-8” の略。

最大4バイト。


ASCIIとは?

American Standard Code for Information Interchangeの略。
最も基本的な文字コード。1960年代に誕生した。

7bitで128文字収録。
ASCII.jpeg
0x00~0x1Fは制御文字(タブや改行など)。


ASCII互換の文字コード

ASCII文字(半角英数字)のビット表現が、ASCIIと一致する文字コードのこと。

  • ASCII互換
    • Shift_JIS
    • EUC-JP
    • UTF-8
  • 非ASCII互換
    • UTF-16
    • UTF-32

[A]という文字はASCII互換では0x41、UTF-16では0x0041。
(後ほど、ビット表現を実際に確認)
半角英数字のビット表現は、Shift_JIS, EUC-JP, UTF-8で同じ。

コンパイラは一般的にASCIIを前提としているので、プログラムファイルはASCII互換の文字コードで保存すること。


文字コードのまとめ

文字コード ASCII互換 バイト数 収録文字
Shift_JIS Yes 1~2 日本語で使う文字
EUC-JP Yes 1~2 日本語で使う文字
UTF-8 Yes 1~4 世界中の文字
UTF-16 No 2~4 世界中の文字

文字コードはUTF-8一択

【メリット】

  • 文字範囲が広い。どの国の文字も表示できる。
    • 多言語化対応に必須
    • ただしフォントが対応していることが条件
  • ASCII互換

【例外】

  • Excel2013以前で開くこと前提のCSVファイル
    • Excel2016でUTF-8に対応しました!!

https://www.marguerite.jp/Nihongo/WWW/RefHTML/HTML5/WhyUTF8.html
https://peta.okechan.net/blog/archives/842/comment-page-1
https://www.ka-net.org/blog/?p=7764


UTF-8はBOMなしがベター

BOM(Byte Order Mark)は、UTF-16, UTF-32でバイトの並び順を示すもの。
UTF-8にBOMは本来関係ないが、「UTF-8」であることを示すマークとして使われる。

BOM付きUTF-8は、ファイルの先頭に3バイト(「EF BB BF」)が付与される。

ファイルの先頭にBOMが付くことを想定していない場合、予期しない結果になることがある。
UTF-8はBOMなしがベター。

http://qiita.com/MuriNishimori/items/a89fe986e28909208e30


[補足] BOM付きUTF-8が原因のエラー

  • BOM付きxmlファイルをEclipse4.6で開くと、1行目にエラーが出る。

    • エラーメッセージ:「プロローグにコンテンツは許されません。」
    • Eclipse4.6で実施
  • BOM付きsqlファイルを、PostgreSQLのpsqlコマンドで実行すると、エラーが出る。

    • エラーメッセージ:「符号化方式"SJIS"における0xef 0xbbバイトシーケンスを持つ文字は"UTF8"符号化方式では等しくありません」
    • PostgreSQL9.6で実施
    • 実行コマンド:psql -U postgres -d sampledb -f sample.sql

[補足] BOM付きUTF-8対策

  • ファイル保存時の文字コード選択肢に"UTF-8"と"UTF-8N"が2つある場合(Terapadなど)は、"UTF-8N"を選択する。"UTF-8N"はBOMなし。
    http://creating-homepage.com/archives/88

  • BOM付きUTF-8ファイルを検索する方法

find . -type f -name '*.xml' -exec file {} + | grep "UTF-8 Unicode (with BOM)"

参考サイト:http://qiita.com/tailak/items/8ba2e738555f8596d3e3

  • bashでBOM付きUTF-8をBOMなしにする方法(nkfコマンドがない場合)
# test.txtを上書き。ただし改行コードがCRLFからLFに変わるかもしれない。
sed -i -e '1s/^\xef\xbb\xbf//' text.txt

http://www.linuxask.com/questions/how-to-remove-bom-from-utf-8-using-sed より参考。


文字コードの自動判別

「どの文字コードで保存されたか」という情報は、テキストファイルに存在しない(UnicodeのBOMを除く)。
文字コードの判別は、「XXというビット表現は文字コードYYYにしか出現しないから、文字コードはYYYだ!」という方法。

  • 確実な自動判別方法はない。
  • 文字列が短いと判別に失敗しやすい。

【私が経験した勘違い】
「abc」という文字をUTF-8でファイル保存して、文字コードを判定すると[Shift_JIS]だった。


[Try] ダンプツールでバイト表現を確認

  • 「aあ」のバイト表現を確認
    • 「a」のバイト表現の違い
    • 「あ」がUTF-8では3バイト
  • UTF-8のBOMを確認
文字コード 「a」のバイト表現 「あ」のバイト表現
Shift_JIS 0x61 0x82 A0
EUC-JP 0x61 0xA4 A2
UTF-8 0x61 0xE3 81 82
UTF-16(リトルエンディアン) 0x61 00 0x42 30

Unixのodコマンドで確認(Git Bashなど)。

 $ od -avtx1 -Ax Shift_JIS.txt

ファイルのダウンロード


[Try] 文字コードの自動判別を確認

【手順】
1. 「aA」という文字をUTF-8で保存する(test.txt)
2. test.txtの中身を「a」に変更する
3. test.txtの文字コードをUnixのfileコマンドで確認する

 $ file test.txt

2. 文字コードの指定方法


前提

  • 全てのファイルの文字コードはUTF-8(BOMなし)

各ファイル内での文字コード宣言

  • HTML
  • CSS
  • XML
  • JSP

文字コード宣言が不要なファイル

  • Java
  • JavaScript
  • properties

HTMLファイル

HTML5の記述方法。

<head>
  <meta charset="UTF-8">
</head>

しかしながら注意点として、HTTPヘッダーによる指定の方が文書内でのmeta指定よりも優先度が高いため、ページ製作者は既にHTTPヘッダーで文字エンコーディングが指定されているかどうかについて常に頭の中に入れておくべきです。

HTMLで文字エンコーディングを指定する より引用


CSSファイル

@charset "UTF-8";

この規則はスタイルシートの最初の要素でなければならず、これより先に一切文字を記述してはいけません。

@charset "UTF-8";       /* スタイルシートのエンコーディングを Unicode UTF-8 にします*/
@charset 'iso-8859-15'; /* 無効値です。正しくない引用符が使用されています */
 @charset "UTF-8";      /* 無効値です。at-規則より前に文字(空白)があります */
@charset UTF-8;         /* 無効値です。' か " がなく、文字セットは CSS の <string> ではありません */

MDN @charset より引用


JSP(作成中)

<%@ page contentType="text/html;charset=UTF-8" %>

文字コードは、contentType属性とpageEncoding属性で指定可能。
ただ、どちらとも省略可能らしい。

http://docs.oracle.com/cd/E18355_01/web.1013/B31860-01/jspnls.htm
http://psycho-cafe.blogspot.jp/2012/01/jsppage-contenttype.html


XML

<?xml version="1.0" encoding="UTF-8"  ?>

HTTP(作成中)

It is very important to always label Web documents explicitly. HTTP 1.1 says that the default charset is ISO-8859-1. But there are too many unlabeled documents in other encodings, so browsers use the reader's preferred encoding when there is no explicit charset parameter.

Setting the HTTP charset parameter より引用

HTTP1.1のデフォルト文字コードはISO-8859-1。
ISO-8859-1は西欧の文字コード(Latin-1)で、日本語は対応していない。

こういった理由から、CharacterEncodingFilterでUTF-8を指定しているはず…


Javaのデフォルト文字コード

Javaでは使用している環境に応じてデフォルトのエンコーディングが決まっており、特に指定しない場合には環境毎のデフォルトエンコーディングを使ってプログラムが保存されていると考えてコンパイルを行います。

文字のエンコーディング確認方法。

System.out.println(System.getProperty("file.encoding"));

Windows環境ではデフォルト「MS932」。
ただしEclipseから実行したときは「UTF-8」。Why?

デフォルトエンコーディングの確認 より引用

デフォルト文字コードの変更方法

JVM オプションで "-Dfile.encoding=UTF-8"を指定する。


3.付録


[Try] サロゲートペアは2文字

サロゲートペアで表現しなくてはいけない文字(マイナーの文字)は、2文字と判定される。

test.js
"a".length; //1
"".length; //1
"𩸽".length; //2
"𩸽".substr(1); //文字化け

Javaでも同様。
サロゲートペア対応用のメソッドもあり。


波ダッシュ問題(作成中)

「~」という文字をShift_JISに変換すると、化けてしまう。

http://qiita.com/kasei-san/items/3ce2249f0a1c1af1cbd2

Shift_JISのWindows版「Windows-31J」を指定すれば、解決。


propertisファイル

かつてはISO-8859-1にしか対応していなかった。
ASCII以外はユニコードエスケープで記述。

Java6以降、UTF-8にも対応している。

http://blog.k11i.biz/2014/09/java-utf-8.html
http://d.hatena.ne.jp/shin/20090707/p4


その他、気にすべき文字コード

ファイル名

OSに依存。
ファイル名はASCIIのみが望ましい。

URL

Tomcat8からはデフォルト文字コードがUTF-8。

ダウンロードファイルの文字コード

HTTPヘッダのContent-Disposition


文字コードの名前

IANA(Internet Assigned Numbers Authority: インターネットに関連する番号を管理する組織) で定義

https://www.iana.org/assignments/character-sets/character-sets.xhtml


おわり

yuji38kwmt
愛知のIT企業で修行しております。2018年4月に転職しました。 基本的に自分用のメモとして、記事を書いております。 所属先の見解とは一切関係ありません。 https://qiita.com/yuji38kwmt/items/a474ad97e0d86f6081a2
kurusugawa
「いいソフトウェアを楽に作る」技術を追求する企業。今は、機械学習、画像認識中心。
http://kurusugawa.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away