文字化け
日本語 | 文字化け |
英語 | transformed character |
ふりがな | もじばけ |
フリガナ | モジバケ |
出力された文字が正しくないこと。
単に「文字が違う」のではなく、たとえば「あ」が「縺」や「?」になっていたりと、全く違う文字になっており、読めない状態になっていることを「文字化けしている」と表現する。
文字化けは、主に2種類の要因によって発生する。
1つは、インターネット等の転送時に途中のデータが消えてしまった場合。Unicodeのように「数バイトで1文字を表現する」文字コードの場合には、途中の1バイトが消えるとそのあとのバイトが全てずれてしまい、全く読めなくなる。
もうひとつは、文字コードの変換時に正しくない文字コードを指定することである。文字コードは基本的に「自動検出」が難しく、自動検出で誤った文字コードと判断されてしまったり、手動設定時に正しくない文字コードを指定していた場合、さらに文字コードを指定できない場合等に発生する。
前者は偶発的に発生するが、後者はバグの一種であり、直さなければならない。
Webアプリケーションの場合、文字化けは入力時にも出力時にも発生しうる。また、入力時にも出力時にも、プログラムが複数組み合わされている場合にはそれぞれで文字コードの変換が必要となる可能性があり、それぞれを正しく設定しなければならない。そのため、Webアプリケーションでは頭の痛い問題である。
文字化けは「出力時の見た目」についての話で、本当に「変な文字に変換された」とは限らない。
たとえば「あ」が「?」として出力されていたとしても、それは出力できないから「?」という文字(0x003F)が代わりに出力されただけで、出力しようとした文字列が「?」という文字というわけではない、かもしれないということである。
これを確かめるため、Stringクラスから「そのままデータとして取り出し出力する」必要がある。そうして出力された内容を「ダンプ」と言い、これを見て、なんの文字コードとして格納されたかを調べるためのヒントにする。
文字化けは、見た目がまったくわけわからず、しかも原因が非常に特定しにくいため、パニックになりやすい。
とりあえず冷静になり、ダンプを使って客観的に判断し、原因を少しずつ絞り込んでいくことが、解決への糸口となるだろう。
単に「文字が違う」のではなく、たとえば「あ」が「縺」や「?」になっていたりと、全く違う文字になっており、読めない状態になっていることを「文字化けしている」と表現する。
文字化けは、主に2種類の要因によって発生する。
1つは、インターネット等の転送時に途中のデータが消えてしまった場合。Unicodeのように「数バイトで1文字を表現する」文字コードの場合には、途中の1バイトが消えるとそのあとのバイトが全てずれてしまい、全く読めなくなる。
もうひとつは、文字コードの変換時に正しくない文字コードを指定することである。文字コードは基本的に「自動検出」が難しく、自動検出で誤った文字コードと判断されてしまったり、手動設定時に正しくない文字コードを指定していた場合、さらに文字コードを指定できない場合等に発生する。
前者は偶発的に発生するが、後者はバグの一種であり、直さなければならない。
Webアプリケーションの場合、文字化けは入力時にも出力時にも発生しうる。また、入力時にも出力時にも、プログラムが複数組み合わされている場合にはそれぞれで文字コードの変換が必要となる可能性があり、それぞれを正しく設定しなければならない。そのため、Webアプリケーションでは頭の痛い問題である。
文字化けは「出力時の見た目」についての話で、本当に「変な文字に変換された」とは限らない。
たとえば「あ」が「?」として出力されていたとしても、それは出力できないから「?」という文字(0x003F)が代わりに出力されただけで、出力しようとした文字列が「?」という文字というわけではない、かもしれないということである。
これを確かめるため、Stringクラスから「そのままデータとして取り出し出力する」必要がある。そうして出力された内容を「ダンプ」と言い、これを見て、なんの文字コードとして格納されたかを調べるためのヒントにする。
文字化けは、見た目がまったくわけわからず、しかも原因が非常に特定しにくいため、パニックになりやすい。
とりあえず冷静になり、ダンプを使って客観的に判断し、原因を少しずつ絞り込んでいくことが、解決への糸口となるだろう。
参考サイト
- (参考サイトはありません)
// Sample.java
import java.io.UnsupportedEncodingException;
// Sample.java
public class Sample
{
public static void main( String[] args )
{
try
{
// たとえば文字コード「シフトJIS」での「あいう」を……
byte[] source = new byte[] { (byte)0x82, (byte)0xA0, (byte)0x82, (byte)0xA2, (byte)0x82, (byte)0xA4 };
// Unicodeに変換せずにセットされてしまうと……
String string = new String( source, "ISO-8859-1" );
System.out.println( string );
// ???¢??
// 文字化けします。
// ただし、ここで出力されている「?」が、実際にstring変数の中に
// 格納されているわけではありません。
// 格納されている文字列を、println()メソッドが出力しようとして
// できなかったから代わりに「?」を出力しているだけです。
// そのため、デバッグする場合には、この中に入っている実際の文字列を
// 取得する必要があります。
// その場合、「16進ダンプ」を出力します。
// 16進数形式で「中身をそのまま出力する」ことで、中に何が入っているのか
// 調べます。
char[] chars = string.toCharArray();
for( int iF1 = 0; iF1 < chars.length; ++iF1 )
{
System.out.println( Integer.toHexString( chars[iF1] ) );
}
// 82
// a0
// 82
// a2
// 82
// a4
// この結果が、sourceの各要素と同じだということを確認してください。
// 慣れてくれば、この値から「シフトJISの『あいう』が入っている」
// ということが直感で分かったりもします。
// 文字化けしてる文字列は、StringクラスのgetBytes()メソッドの
// の引数に"ISO-8859-1"を渡してbyte型配列として取りだしたあと、
// 正しい文字コードで渡し直します。
byte[] bytes = string.getBytes( "ISO-8859-1" );
string = new String( bytes, "Shift_JIS" );
System.out.println( string );
// あいう
// ただし、これができるのは、
// String string = new String( source, "ISO-8859-1" );
// の箇所で"ISO-8859-1"を指定することで「全く変換せずにセットしている」
// ためです。
// もしこの時になんらかの文字コードを指定してしまっていると、
// 無理矢理変換してデータが壊れてしまうため、もう元には
// 戻りません。
}
catch( UnsupportedEncodingException e )
{
// StringクラスのコンストラクタがUnsupportedEncodingException例外を
// 投げるので拾います。第2引数で渡された文字コード
// (上記の例では「ISO-8859-1」や「Shift_JIS)が、Javaではサポート
// されていない文字コードの場合にエラーとなります。
e.printStackTrace();
}
}
}
import java.io.UnsupportedEncodingException;
// Sample.java
public class Sample
{
public static void main( String[] args )
{
try
{
// たとえば文字コード「シフトJIS」での「あいう」を……
byte[] source = new byte[] { (byte)0x82, (byte)0xA0, (byte)0x82, (byte)0xA2, (byte)0x82, (byte)0xA4 };
// Unicodeに変換せずにセットされてしまうと……
String string = new String( source, "ISO-8859-1" );
System.out.println( string );
// ???¢??
// 文字化けします。
// ただし、ここで出力されている「?」が、実際にstring変数の中に
// 格納されているわけではありません。
// 格納されている文字列を、println()メソッドが出力しようとして
// できなかったから代わりに「?」を出力しているだけです。
// そのため、デバッグする場合には、この中に入っている実際の文字列を
// 取得する必要があります。
// その場合、「16進ダンプ」を出力します。
// 16進数形式で「中身をそのまま出力する」ことで、中に何が入っているのか
// 調べます。
char[] chars = string.toCharArray();
for( int iF1 = 0; iF1 < chars.length; ++iF1 )
{
System.out.println( Integer.toHexString( chars[iF1] ) );
}
// 82
// a0
// 82
// a2
// 82
// a4
// この結果が、sourceの各要素と同じだということを確認してください。
// 慣れてくれば、この値から「シフトJISの『あいう』が入っている」
// ということが直感で分かったりもします。
// 文字化けしてる文字列は、StringクラスのgetBytes()メソッドの
// の引数に"ISO-8859-1"を渡してbyte型配列として取りだしたあと、
// 正しい文字コードで渡し直します。
byte[] bytes = string.getBytes( "ISO-8859-1" );
string = new String( bytes, "Shift_JIS" );
System.out.println( string );
// あいう
// ただし、これができるのは、
// String string = new String( source, "ISO-8859-1" );
// の箇所で"ISO-8859-1"を指定することで「全く変換せずにセットしている」
// ためです。
// もしこの時になんらかの文字コードを指定してしまっていると、
// 無理矢理変換してデータが壊れてしまうため、もう元には
// 戻りません。
}
catch( UnsupportedEncodingException e )
{
// StringクラスのコンストラクタがUnsupportedEncodingException例外を
// 投げるので拾います。第2引数で渡された文字コード
// (上記の例では「ISO-8859-1」や「Shift_JIS)が、Javaではサポート
// されていない文字コードの場合にエラーとなります。
e.printStackTrace();
}
}
}
// Sample.java import java.io.UnsupportedEncodingException; // Sample.java public class Sample { public static void main( String[] args ) { try { // たとえば文字コード「シフトJIS」での「あいう」を…… byte[] source = new byte[] { (byte)0x82, (byte)0xA0, (byte)0x82, (byte)0xA2, (byte)0x82, (byte)0xA4 }; // Unicodeに変換せずにセットされてしまうと…… String string = new String( source, "ISO-8859-1" ); System.out.println( string ); // ???¢?? // 文字化けします。 // ただし、ここで出力されている「?」が、実際にstring変数の中に // 格納されているわけではありません。 // 格納されている文字列を、println()メソッドが出力しようとして // できなかったから代わりに「?」を出力しているだけです。 // そのため、デバッグする場合には、この中に入っている実際の文字列を // 取得する必要があります。 // その場合、「16進ダンプ」を出力します。 // 16進数形式で「中身をそのまま出力する」ことで、中に何が入っているのか // 調べます。 char[] chars = string.toCharArray(); for( int iF1 = 0; iF1 < chars.length; ++iF1 ) { System.out.println( Integer.toHexString( chars[iF1] ) ); } // 82 // a0 // 82 // a2 // 82 // a4 // この結果が、sourceの各要素と同じだということを確認してください。 // 慣れてくれば、この値から「シフトJISの『あいう』が入っている」 // ということが直感で分かったりもします。 // 文字化けしてる文字列は、StringクラスのgetBytes()メソッドの // の引数に"ISO-8859-1"を渡してbyte型配列として取りだしたあと、 // 正しい文字コードで渡し直します。 byte[] bytes = string.getBytes( "ISO-8859-1" ); string = new String( bytes, "Shift_JIS" ); System.out.println( string ); // あいう // ただし、これができるのは、 // String string = new String( source, "ISO-8859-1" ); // の箇所で"ISO-8859-1"を指定することで「全く変換せずにセットしている」 // ためです。 // もしこの時になんらかの文字コードを指定してしまっていると、 // 無理矢理変換してデータが壊れてしまうため、もう元には // 戻りません。 } catch( UnsupportedEncodingException e ) { // StringクラスのコンストラクタがUnsupportedEncodingException例外を // 投げるので拾います。第2引数で渡された文字コード // (上記の例では「ISO-8859-1」や「Shift_JIS)が、Javaではサポート // されていない文字コードの場合にエラーとなります。 e.printStackTrace(); } } }