!!!Javaでの文字コードの扱い [Java]{{category 文字化け}} なんだかんだといつも厄介な文字コードの変換についてのメモ 結局、ファイル読込み、文字列変数の取り扱い、ファイル書き込みなどの各局面で、実際はどの文字コードが使用されているかを考え、適切にコンバートすることが肝要 *[インターネットの言葉と技術|http://www.kanzaki.com/netfan/] *[Javaでの文字コードの扱い|https://www.typea.info/tips_/index.php/Java%E3%81%A7%E3%81%AE%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%89%B1%E3%81%84#Java.E3.81.A7.E3.81.AE.E6.96.87.E5.AD.97.E3.82.B3.E3.83.BC.E3.83.89.E3.81.AE.E6.89.B1.E3.81.84] !!Javaに限らず、厄介な文字化けについて {{category 文字化け}} {{amazon 477414164X}} {{amazon 481633243X}} !!基本事項 !Stringクラス ::仕様では、[String クラス|http://www.y-adagio.com/public/standards/tr_javalang2/typesValues.doc.html#26992]はUnicode文字の並びを表す *String クラスのソースコード(%JAVA_HOME%/src.zip)を見ると、Unicode文字の並びをchar型の配列として保持している。 *[char型|http://www.y-adagio.com/public/standards/tr_javalang2/typesValues.doc.html#48440]は、[Unicode|http://e-words.jp/w/Unicode.html]文字を表す16ビット符号無し整数で、'\u0000'〜'\uffff' すなわち 0〜65535を表現できる *Javaで扱うUnicodeは、1文字を16ビット(2バイト)[UCS-2|http://e-words.jp/w/UCS-2.html]である。 *現在はUnicode全体は4バイトで定義([UCS-4|http://e-words.jp/w/UCS-4.html])されている。 !ソースコードの変換 ::ソースコードのコンパイル時、プラットフォームの文字コードやファイルの文字コードに依存してしまう。 *Windowsでソースを書いてLinuxでコンパイルを行ったりするような場合には、プラットフォームとソースコードの文字コードの不一致によって文字化けが発生する。 *[native2ascii|http://java.sun.com/j2se/1.5.0/ja/docs/ja/tooldocs/windows/native2ascii.html] を使用して、ソースコードに含まれるUnicode以外の文字を、[Unicodeエスケープ|http://www.y-adagio.com/public/standards/tr_javalang2/lexical.doc.html#100850]に変換する。 ::プロパティファイルの変換 *プロパティファイル等、Java プログラムで利用するファイルも、ソースコード同様、[native2ascii|http://java.sun.com/j2se/1.5.0/ja/docs/ja/tooldocs/windows/native2ascii.html] を使用して文字コードを変換する。 !!ファイルの読み書き プログラムの実行時にファイルを読込む必要がある場合等は、ファイルに合わせた文字コードでファイルを読まなければ文字化けしてしまう場合がある。 !文字コードを指定してファイルを読む ::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 ::文字コードをiso-8859-1として変換 *http://ja.wikipedia.org/wiki/ISO/IEC_8859-1 *Spring の場合 @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拡張文字)や〜‖−¢£¬などの扱いが異なり、誤って使用すると“?”に文字化け *http://www.atmarkit.co.jp/fjava/rensai2/webopt08/webopt08.html *文字コード 参照 ::円記号 *Shift_JISでは、半角円記号とバックスラッシュを区別しないが、する文字コード体系だと見た目上は、半角円記号なのに、Stringのメソッドが正しく動作しない(ように見える) String str1 = "\u005c\u005c"; String str2 = "\u00a5"; System.out.println(str1 + " = " + str2); System.out.println(str1.equals(str2)); \ = \ false !!ファイルの文字コードを判別する *[[ファイルの文字コードを判別する|Java ファイルの文字コードを判別する]] !!その他 {{amazon 4774107808}} !Webアプリケーションの文字化け対策 *Filterで文字化け対策 *文字化けの対処 ---- {{amazon 4822282775}} Java5.0でだいぶ機能追加があったけれど、丁寧に説明してくれてます。 試験対策でなくても非常に有用 {{amazon 482228168X}} ただ、試験範囲から外れちゃったところも多いので、こちらの本もあわせて読んでおくとよいかも(もったいないか?) {{include_html banner_html, "!amazon_promotion2"}} !!その他文字化けについて {{category 文字化け}} *Excel VBA 文字列をバイト配列に変換 *Filterで文字化け対策 *HTML javascript:を利用するとデコードされる *J2EE Tips *Java ファイルの文字コードを判別する *Javaでの文字コードの扱い *Linux バックスペースが文字化けしてしまう *Python URLエンコード *Python UnicodeEncodeError の対処 *Python ファイルの文字コード *SQL Plus *WAS から Java Mail送信で文字化け *vi *画面に入力された文字コードを調べる *文字コード *文字化けの対処 {{include_html redirect_html, "!JAVA_CHAR_CODE"}}