ホームページ  >  記事  >  Java  >  JAVA WEB 注意事項 - 中国語文字化け

JAVA WEB 注意事項 - 中国語文字化け

巴扎黑
巴扎黑オリジナル
2017-06-26 11:11:011513ブラウズ

JAVA WEB コード化けの問題分析

コード化けの原因

Java Web 開発の過程で、コード化けの問題によく遭遇します。コード化けの原因は、文字エンコーディングとデコード方法の不一致に要約できます。 。

文字化けの原因は文字エンコードとデコード方法が合っていないことなので、なぜエンコードしなければならないのでしょうか?これは、コンピューターにデータを保存する基本単位が 1 バイト、つまり 8 ビットであるため、表現できる最大文字数は 28=256 であり、私たちの現実社会に存在する文字 (中国語)文字、英語、その他の文字など)はこの数をはるかに超えているため、文字とバイトの間の競合を解決するには、文字をコンピュータに保存する前にエンコードする必要があります。

エンコードとデコード

コンピュータにおける一般的なエンコード方式には、ASCII、ISO-8859-1、GB2312、UTF-16、UTF-8などがあります。

ASCIIコードはバイトの下位7ビットで表現されるので、表現できる最大文字数は27=128です。 ISO-8859-1 は、ASCII コードに基づく ISO 組織の拡張であり、ASCII コードと互換性があり、ほとんどの西ヨーロッパ文字をカバーします。 ISO8859-1 は 1 バイトで表現するため、最大 256 文字を表現できます。 GB2312 は 2 バイト エンコードを使用します。エンコード範囲は A1 ~ F7 です。A1 ~ A9 は記号領域、B0 ~ F7 は 6763 個の漢字を含む漢字領域です。 GBK は、GB2312 エンコーディングを拡張し、さらに多くの漢字を追加したものです。表現できる漢字は 21,003 文字です。 UTF-16 は、どの文字でも 2 バイトで表される固定長エンコーディング方式を使用します。これは、JAVA メモリ内の文字の格納形式でもあります。 UTF-16 とは対照的に、UTF-8 は可変長エンコード方式を使用し、さまざまな種類の文字を 1 ~ 6 バイトで構成できます。

以下に示すように、文字列「日向ヒナタ」を使用して、コンピューターでのさまざまなエンコード方法のエンコードを見てみましょう。

コード化け解析と解決策

JAVA WEBのコード化け問題について、リクエストによるコード化けとレスポンスによるコード化けに分けて、それぞれのコード化けについて説明します。コード、つまり文字化けの原因を分析する必要があります。エンコード方式とデコード方式は何ですか。

リクエストによるコード化けについては、HTTPリクエストを解析し、そのエンコード方法を確認する必要があります。HTTPリクエストはGetリクエストとPostリクエストに分けて説明します。

Getリクエストの場合、ブラウザのデフォルトのリクエストメソッドであり、送信時にフォームを「Get」に設定した場合の送信メソッドです。 Firefox ブラウザを通じて次のように特定のコンテンツを確認します。

アドレス バーは次のとおりです。

リクエストのコンテンツは次のとおりです。

文字列はリクエスト ラインに保存され、WEB サーバーに送信されます。 「日向ヒナタ」のエンコードにより、ブラウザで文字列に使用されているエンコード方式が「UTF-8」であることがわかります。

サーバーのコードを見ると、文字化けが見られます (以下に示すように)。これは、サーバーがデフォルトで ISO-8859-1 を使用して文字列エンコードを受信した後にデータをデコードするため、エンコードとデコードが発生します。アプローチは一律ではありません。解決策の概略図は次のとおりです。

Java Web開発のプロセスでは、ハイパーリンクでパラメータを渡しますが、しばしば中国語の状況に遭遇します。この場合、中国語をエンコードする必要があります。UTF-8 に設定できます。デコード スキームは上記と同じです。

<a href="${pageContext.request.contextPath}/Test?user=<%=URLEncoder.encode("日向雏田", "UTF-8")%>">点击</a>

Postリクエストの場合、フォーム送信を「投稿」に設定した場合の送信方法です。次のように、Firefoxブラウザを介して特定のコンテンツを確認します。上の図では、post リクエストでは、リクエストの内容がリクエストボディに直接配置されて Web サーバーに送信され、エンコード方式が「utf-8」であることがわかります。

このレスポンスサーブレットでは、doPostメソッド本体は以下の通りです:

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String user=request.getParameter("user");
		System.out.println(user);//输出为日向雏田
	}

ここでコードが文字化けする理由は、やはりコード getParameter ("user") を実行したときです。 Web サーバーはデフォルトのデコード スキーム「ISO-8859-1」を使用し、デコードされるため、エンコード スキームとデコード スキームの間に不一致が生じます。解決策としては、get リクエストの文字化け解決策を使用することもできますが、直接行うより簡単な解決策もあります。 /Decoding スキームが「utf-8」であることを指定します。計画は以下の通りです。以上でリクエストによるコード化けの解析は完了です。

影響によるコード化けでは、Web サーバーはステータス行を介さずに応答内容を応答本文に書き込み、クライアントに返します。例えばブラウザに「HelloWorld」を出力した場合、レスポンスは下図のようになります。

レスポンスによって引き起こされるコード化けには、次の 4 つのメソッドを含める必要があります。

エンコードタイプの設定用応答本文の (response.setHeader("Content-Type", "text/html;cahrset=utf-8") および response.setCharacterEncoding("utf-8"); これら 2 つのメソッドによって設定されるエンコード方式レスポンスボディのエンコード方式を設定する場合、デフォルトは ISO-8859-1 であり、後でレスポンスボディの文字のエンコード方式を設定すると、以前の設定のエンコード方式が繰り返されます。どちらのメソッドもgetWriterメソッドより前に有効となり、getWriterメソッドでのエンコーディングの設定メソッドは無効となります。

しかし、これら 2 つのメソッドは少し異なります。つまり、setHeader("Content-Type", "text/html;cahrset=utf-8") のメソッドでは、ブラウザは自動的に次のエンコーディング メソッドを使用します。デコードする応答本文。すべてのブラウザがこのメソッドのエンコーディング メソッドを使用して setCharacterEncoding() メソッドをデコードするわけではありません。以下で 2 つのメソッドをテストし、結果は次のとおりです。 りー

  

 

   从上面可以看到第一个方法对于浏览器来说,支持的较好,提倡采用第一种方法设置响应体的字符编码方式。

  对于获取响应字符输出流的方法,如果在此之前没有设置响应体的编码方式,那么默认为null,即ISO-8859-1方式进行编码。而且后面设置的编码方式会覆盖前面设置的编码方式。在getWriter()方法之后设置的编码无效。

  对于获取响应输出字节流,我们在输出字符串时,我们需要设置字符串的编码方式如果没有那么默认ISO-8859-1。

  对于前面2个输出流,由于只有一个输出缓存,所以这两个方法互斥。

  以上,为了保证响应无乱码,需要保证字符编码和解码方法的统一,方案如下:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
//	方案1
//		response.setHeader("Content-Type", "text/html;charset=utf-8");
//		response.getWriter().write("日向雏田");
//	方案2
//		response.getOutputStream().write("日向雏田".getBytes("UTF-8"));
//	方案1,2互斥
	}

  

   此外在Java web开发过程中,我们还会遇到当进行文件下载时,中文文件名导致的问题,如下图所示:

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String realPath=this.getServletContext().getRealPath("/src/日向雏田.jpg");
		String fileName=realPath.substring(realPath.lastIndexOf(&#39;\\&#39;)+1);
		response.setHeader("content-disposition", "attachment;filename="+fileName);
		InputStream is=new FileInputStream(new File(realPath));
		OutputStream os=response.getOutputStream();
		byte[] buff=new byte[1024];
		int len=0;
		while((len=is.read(buff))>0){
			os.write(buff, 0, len);
		}
		os.close();
		is.close();
	}

  采用火狐浏览器进行测试,查看页面效果,及其响应结果如下:

  

  经过查看响应头分析,下载文件名存放在响应头中,且对于中文文字没有采用UTF-8、UTF-16、GBK等等能识别中文的编码,那么对于中文文件名导致采用哪种编码方式呢?查看REF 7578得知,在此处采用ASCII编码,但是REF规定,如果不可避免的要使用非ASCII码的字符,程序员应该均匀的使用UTF-8,来最小化交互操作的问题。

  所以,解决方案就是把文件名编码成UTF-8,传递给响应头,浏览器(部分)默认对该文件名进行UTF-8解码处理。

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String realPath=this.getServletContext().getRealPath("/src/日向雏田.jpg");
		String fileName=realPath.substring(realPath.lastIndexOf(&#39;\\&#39;)+1);
		String utf_8Name=URLEncoder.encode(fileName,"utf-8");//解决方案
		response.setHeader("content-disposition", "attachment;filename="+utf_8Name);
		InputStream is=new FileInputStream(new File(realPath));
		OutputStream os=response.getOutputStream();
		byte[] buff=new byte[1024];
		int len=0;
		while((len=is.read(buff))>0){
			os.write(buff, 0, len);
		}
		os.close();
		is.close();
	}

  效果如下:其中火狐浏览器并没有对其解码

 

以上がJAVA WEB 注意事項 - 中国語文字化けの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。