目次
Javaでの文字コードの扱い
なんだかんだといつも厄介な文字コードの変換についてのメモ
結局、ファイル読込み、文字列変数の取り扱い、ファイル書き込みなどの各局面で、実際はどの文字コードが使用されているかを考え、適切にコンバートすることが肝要
Javaに限らず、厄介な文字化けについて
[文字化け]
基本事項
Stringクラス
- 仕様では、String クラスはUnicode文字の並びを表す
- String クラスのソースコード(%JAVA_HOME%/src.zip)を見ると、Unicode文字の並びをchar型の配列として保持している。
- char型は、Unicode文字を表す16ビット符号無し整数で、'\u0000'〜'\uffff' すなわち 0〜65535を表現できる
- Javaで扱うUnicodeは、1文字を16ビット(2バイト)UCS-2である。
- 現在はUnicode全体は4バイトで定義(UCS-4)されている。
ソースコードの変換
- Windowsでソースを書いてLinuxでコンパイルを行ったりするような場合には、プラットフォームとソースコードの文字コードの不一致によって文字化けが発生する。
- native2ascii を使用して、ソースコードに含まれるUnicode以外の文字を、Unicodeエスケープに変換する。
- プロパティファイルの変換
- プロパティファイル等、Java プログラムで利用するファイルも、ソースコード同様、native2ascii を使用して文字コードを変換する。
ファイルの読み書き
プログラムの実行時にファイルを読込む必要がある場合等は、ファイルに合わせた文字コードでファイルを読まなければ文字化けしてしまう場合がある。
文字コードを指定してファイルを読む
- FileInputStream を利用することにより、文字コードを指定してファイルを読むことができる
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("/var/files/ebicdic.txt"),"Cp943c"));
文字コードを指定してファイルを書く
- FileInputStream を利用することにより、文字コードを指定してファイルを書くことができる
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:\\shift_jis.txt"), "MS932"))
文字コードの変換
"Unicodeで定義された文字集合で表現された文字列" から "バイト列" へのエンコード方法、逆にデコード方法を指定する。
エンコード
- エンコード方式(文字セット)を指定して、Stringからバイト列を取得する
byte[] String.getBytes(String charsetName)
- java.lang.StringCoding.encode(String charsetName, char[] value ...)
- sun.io.CharToByteConverter
デコード
- デコード方式(文字セット)を指定して、バイト列からStringを生成する
new String(byte[] bytes, String charsetName)
- java.lang.StringCoding.decode(String charsetName, byte[] bytes ...)
- sun.io.ByteToCharConverter
文字コードの変換
- 上記を使用して、文字コードを変換する
String newCode = new String(oldCode.getBytes("Cp930"), "MS932");
デフォルトエンコード(デコード)
- エンコード(デコード)方式を指定しないと、プラットフォームのデフォルトエンコーディングが使用される。
システムプロパティ
名前 | 説明 | 例 |
---|---|---|
file.encoding | デフォルトのコード系 | MS932 |
file.encoding.pkg | コード系を取り扱うパッケージ | sun.io |
line.separator | 行のセパレータ | CRLF |
- System.getProperty("file.encoding")
- sun.io.Converters.getDefaultEncodingName()
文字コードの16進ダンプ
- デバッグ用
public static String stringDump(String s) { if (s == null) return ""; StringBuffer buf = new StringBuffer(); char[] c = s.toCharArray(); for (int i=0; i<c.length; i++) { buf.append(Integer.toString((int)c[i], 16) + " "); } return buf.toString(); }
文字コードの16進ダンプを復元
- デバッグ用
public static String decodeDumpString(String s) { StringBuffer result = new StringBuffer(); StringTokenizer tok = new StringTokenizer(s.trim(), " "); List lst = new ArrayList(); while(tok.hasMoreTokens()) { lst.add(new Character((char)Integer.parseInt(tok.nextToken(),16))); } char[] buf = new char[lst.size()]; for (int i=0; i<lst.size(); i++) { buf[i] = ((Character)lst.get(i)).charValue(); } return (new String(buf)); }
エンコーディング
- エンコーディングの別名一覧
- MS932またはSJISの別名として定義されており、どちらの別名となるかはバージョンに依存している(JDK 1.3ではMS932だが、JDK 1.4ではSJISとなる)。
- http://www.atmarkit.co.jp/fjava/rensai2/webopt08/webopt08.html
- CP943cとShift_JISの文字コードの違いについて
マルチパートのエンコード
ファイルアップロードの場合にファイル名が文字化けする
- Form
<form id="formUpload" action="upload.html" method="POST" enctype="multipart/form-data" > <input name="attach_file" /> <input type="submit" value="アップロード"/> </form>
- 文字コードをiso-8859-1として変換
@RequestMapping(value="/upload.html", method = RequestMethod.POST) public String uploadFile(MultipartFile file) { String filename = new String(file.getOriginalFilename().getBytes("iso-8859-1"),"utf-8"); :
ファイルダウンロード時にファイル名が文字化けする
//String fileName = new String(originalFileName.getBytes("utf-8"),"iso-8859-1"); // Chrome OK, IE NG String fileName = new String(originalFileName.getBytes("ms932"),"iso-8859-1"); // Chrome OK, IE OK response.setHeader("Content-Type", "application/octet-stream"); response.setHeader("Content-Disposition", "filename=\"" + fileName + "\"");
Shift_JISの取り扱い
- MS932またはSJISの別名として定義されており、どちらの別名となるかはバージョンに依存している(JDK 1.3ではMS932だが、JDK 1.4ではSJISとなる)。
- 機種依存文字(NEC特殊文字、NEC選定IBM拡張文字、IBM拡張文字)や〜‖−¢£¬などの扱いが異なり、誤って使用すると“?”に文字化け
- 文字コード 参照
- 円記号
- Shift_JISでは、半角円記号とバックスラッシュを区別しないが、する文字コード体系だと見た目上は、半角円記号なのに、Stringのメソッドが正しく動作しない(ように見える)
String str1 = "\u005c\u005c"; String str2 = "\u00a5"; System.out.println(str1 + " = " + str2); System.out.println(str1.equals(str2));
\ = \ false
ファイルの文字コードを判別する
その他
Webアプリケーションの文字化け対策
Java5.0でだいぶ機能追加があったけれど、丁寧に説明してくれてます。
試験対策でなくても非常に有用
ただ、試験範囲から外れちゃったところも多いので、こちらの本もあわせて読んでおくとよいかも(もったいないか?)
その他文字化けについて
[文字化け]
- Excel VBA 文字列をバイト配列に変換
- Filterで文字化け対策
- HTML javascript:を利用するとデコードされる
- J2EE Tips
- Java ファイルの文字コードを判別する
- Javaでの文字コードの扱い
- Linux バックスペースが文字化けしてしまう
- Python URLエンコード
- Python UnicodeEncodeError の対処
- Python ファイルの文字コード
- SQL Plus
- WAS から Java Mail送信で文字化け
- vi
- 画面に入力された文字コードを調べる
- 文字コード
- 文字化けの対処
YAGI Hiroto (piroto@a-net.email.ne.jp)
twitter http://twitter.com/pppiroto
Copyright© 矢木 浩人 All Rights Reserved.