HTMLでのUTF-8エンコーディングに関する質問を1つ1つ訪問しましたが、期待どおりに機能しているようには見えません。
meta
タグを追加しました。何も変更されていません。
私はaccept-charset
form
の属性:何も変更されていません。
<%@ page pageEncoding="UTF-8" %>
<%@ taglib uri="http://Java.Sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Editer les sous-titres</title>
</head>
<body>
<form method="post" action="/Subtitlor/edit" accept-charset="UTF-8">
<h3 name="nameOfFile"><c:out value="${ nameOfFile }"/></h3>
<input type="hidden" name="nameOfFile" id="nameOfFile" value="${ nameOfFile }"/>
<c:if test="${ !saved }">
<input value ="Enregistrer le travail" type="submit" style="position:fixed; top: 10px; right: 10px;" />
</c:if>
<a href="/Subtitlor/" style="position:fixed; top: 50px; right: 10px;">Retour à la page d'accueil</a>
<c:if test="${ saved }">
<div style="position:fixed; top: 90px; right: 10px;">
<c:out value="Travail enregistré dans la base de donnée"/>
</div>
</c:if>
<table border="1">
<c:if test="${ !saved }">
<thead>
<th style="weight:bold">Original Line</th>
<th style="weight:bold">Translation</th>
<th style="weight:bold">Already translated</th>
</thead>
</c:if>
<c:forEach items="${ subtitles }" var="line" varStatus="status">
<tr>
<td style="text-align:right;"><c:out value="${ line }" /></td>
<td><input type="text" name="line${ status.index }" id="line${ status.index }" size="35" /></td>
<td style="text-align:right"><c:out value="${ lines[status.index].content }"/></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
for (int i = 0 ; i < 2; i++){
System.out.println(request.getParameter("line"+i));
}
Et ton père et sa soeur
Il ne sera jamais parti.
meta
タグを追加しました:何も変更されませんでした。
実際に、ページがHTTP経由ではなくHTTP経由で提供されている場合は効果がありません。ローカルディスクファイルシステムから(つまり、ページのURLは_http://...
_ではなく_file://...
_です)。 HTTPでは、HTTP応答ヘッダーの文字セットが使用されます。次のように設定済みです。
_<%@page pageEncoding="UTF-8"%>
_
これにより、UTF-8を使用してHTTP応答が書き出されるだけでなく、_Content-Type
_応答ヘッダーにcharset
属性も設定されます。
これは、Webブラウザーが応答を解釈し、HTMLフォームのパラメーターをエンコードするために使用されます。
form
に_accept-charset
_属性を追加しました:何も変更されませんでした。
Microsoft Internet Explorerブラウザーでのみ効果があります。それでもそれは間違ってそれをしています。絶対に使用しないでください。実際のすべてのWebブラウザーは、代わりに応答の_Content-Type
_ヘッダーで指定されたcharset
属性を使用します。 MSIEでも、_accept-charset
_属性を指定するしない限り、正しく実行されます。前に述べたように、pageEncoding
ですでに適切に設定されています。
meta
タグと_accept-charset
_属性の両方を削除します。それらは有益な効果はなく、長期的に混乱するだけでなく、エンドユーザーがMSIEを使用する場合に事態を悪化させるだけです。 pageEncoding
に固執するだけです。すべてのJSPページでpageEncoding
を繰り返す代わりに、以下のように_web.xml
_でグローバルに設定することもできます。
_<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
_
前述のように、これにより、JSPエンジンはUTF-8を使用してHTTP応答出力を書き込み、HTTP応答ヘッダーにも設定するようになります。 Webブラウザーは、サーバーに送り返す前に、同じ文字セットを使用してHTTP要求パラメーターをエンコードします。
不足している唯一の手順は、getParameterXxx()
呼び出しで戻る前に、HTTP要求パラメーターをデコードするためにUTF-8を使用する必要があることをサーバーに伝えることです。これをグローバルに行う方法は、HTTP要求メソッドによって異なります。 POSTメソッドを使用している場合、これは、すべての要求を自動的にフックする以下のサーブレットフィルタークラスで比較的簡単に実現できます。
_@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
// NOOP.
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
@Override
public void destroy() {
// NOOP.
}
}
_
それで全部です。サーブレット3.0以降(Tomcat 7以降)では、追加の_web.xml
_構成は必要ありません。
setCharacterEncoding()
メソッドがbeforebefore POSTリクエストが呼び出されることが非常に重要であることを覚えておく必要がありますパラメータは、getParameterXxx()
メソッドのいずれかを使用して初めて取得されます。これは、最初のアクセスで一度だけ解析され、サーバーのメモリにキャッシュされるためです。
したがって、たとえば以下のシーケンスはwrongです:
_String foo = request.getParameter("foo"); // Wrong encoding.
// ...
request.setCharacterEncoding("UTF-8"); // Attempt to set it.
String bar = request.getParameter("bar"); // STILL wrong encoding!
_
サーブレットフィルタでsetCharacterEncoding()
ジョブを実行すると、(少なくともサーブレットの前に)タイムリーに実行されることが保証されます。
サーバーにUTF-8を使用してGET(POSTではなく)要求パラメーター(URLの_?
_文字の後に表示されるパラメーター)もデコードするように指示する場合は、基本的に次のようにする必要があります。サーバー側で構成します。サーブレットAPIを介して構成することはできません。たとえば、Tomcatをサーバーとして使用している場合は、Tomcat独自の_URIEncoding="UTF-8"
_の_<Connector>
_要素に_/conf/server.xml
_属性を追加するだけです。
System.out.println()
呼び出しのコンソール出力に Mojibake が引き続き表示される場合は、stdout自体がUTF-8を使用するように構成されていない可能性が高くなります。それを行う方法は、stdoutを解釈して提示する責任がある人によって異なります。たとえばEclipseをIDEとして使用している場合は、Window> Preferences> General> Workspace> Text File EncodingをUTF-8に設定するだけです。
まず、コンピュータはビット(0と1)以外は何も理解しないことを知っているという普遍的な事実から始めましょう。
ここで、HTTPを介してHTMLフォームを送信し、値が回線を経由して宛先サーバーに到達すると、基本的には多くのビット-0と1が渡されます。
これのアナロジーは次のようになります-私はあなたに手紙を送り、それが英語、フランス語、またはオランダ語のどちらで書かれているかを伝えます。私があなたに送るつもりであったように正確なメッセージを受け取ります。そして、私に返信する際に、私がどの言語で読むべきかについても言及します。
重要なポイントは、データがクライアントから送信されるときにエンコードされ、サーバー側でも同じようにデコードされるという事実です。何も指定しない場合、コンテンツは application/x-www-form-urlencoded に従ってエンコードされてから、クライアント側からサーバー側に移動します。
ウォームアップを読むことは重要です。期待される結果を得るために確認する必要があることがいくつかあります。
これを確実にするために、いくつかの方法が話されていますが、私は HTTP Accept-Charset request-header field を使用すると言います。提供されたコードスニペットに従って、すでに使用しており、正しく使用しているため、その面で優れています。
これを使用しない、または実装されていないと言う人もいますが、私は非常に謙虚に反対します。 _Accept-Charset
_はHTTP 1.1仕様の一部であり(私はリンクを提供しました)、HTTP 1.1を実装するブラウザは同じものを実装します。 Accept request-header field's "charset"属性を使用すると主張するかもしれませんが、
言葉だけでなく、すべてのデータと事実を提供しますが、それでも満足できない場合は、さまざまなブラウザを使用して次のテストを行ってください。
accept-charset="ISO-8859-1"
_を設定します。サーバーで予期された文字を見ることができなかったことがわかります。ただし、同じコード化スキームを使用する場合は、期待される文字が表示されます。したがって、ブラウザは_accept-charset
_を実装し、その効果が発揮されます。
これを達成するためにあなたができることについて話している地獄の多くの方法があります(特定のシナリオに基づいていくつかの構成が必要になる場合がありますが、以下は95%のケースを解決し、あなたのケースにも適しています)。例えば:
setCharacterEncoding
を使用-Dfile.encoding=utf8
_などを使用して、Webまたはアプリケーションサーバーを正しい文字エンコーディングに設定します。続きを読む こちら私のお気に入りは最初のもので、あなたの問題も解決します-以下の理由により「文字エンコーディングフィルター」:
以下を実行して、独自の文字エンコーディングフィルターを実装できます。 Springsなどのフレームワークを使用している場合は、独自のクラスを記述する必要はなく、web.xmlで構成するだけです
以下のコアロジックは、Springが行うことと非常によく似ていますが、多くの依存関係は別として、Beanが行うことを認識しています。
web.xml(構成)
_<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>
com.sks.hagrawal.EncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
_
EncodingFilter(文字エンコーディング実装クラス)
_public class EncodingFilter implements Filter {
private String encoding = "UTF-8";
private boolean forceEncoding = false;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding(encoding);
if(forceEncoding){ //If force encoding is set then it means that set response stream encoding as well ...
response.setCharacterEncoding(encoding);
}
filterChain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
String encodingParam = filterConfig.getInitParameter("encoding");
String forceEncoding = filterConfig.getInitParameter("forceEncoding");
if (encodingParam != null) {
encoding = encodingParam;
}
if (forceEncoding != null) {
this.forceEncoding = Boolean.valueOf(forceEncoding);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
_
これは基本的に文字エンコーディングフィルターで行われるのと同じコードですが、フィルターで行うのではなく、サーブレットまたはコントローラークラスで行います。
ここでも、httpリクエストストリームの読み取りを開始する前に、request.setCharacterEncoding("UTF-8");
を使用してhttpリクエストストリームのエンコーディングを設定することをお勧めします。
以下のコードを試してみてください。リクエストオブジェクトのエンコーディングを設定するためになんらかのフィルタを使用していない場合、最初のログはNULLになり、2番目のログは「UTF-8」になります。
_System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
request.setCharacterEncoding("UTF-8");
System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
_
以下は setCharacterEncoding Java docs からの重要な抜粋です。注意すべきもう1つの点は、有効なエンコードスキームを提供する必要があることです。それ以外の場合はUnsupportedEncodingException
オーバーライドこのリクエストの本文で使用される文字エンコーディングの名前。 このメソッドは、リクエストパラメータを読み取る前、またはgetReader()を使用して入力を読み取る前に呼び出す必要があります。それ以外の場合、影響はありません。
あなたが信頼を築くことができるように、必要なところはどこでも、私はあなたに公式リンクまたはStackOverflowが受け入れた賞金の回答を提供するために最善を尽くしました。
あなたの投稿された出力に基づいて、パラメータはUTF8として送信され、後で文字列のUnicodeバイトがISO-8859-1として解釈されるようです。
次のスニペットは、観察された動作を示しています
String eGrave = "\u00E8"; // the letter è
System.out.printf("letter UTF8 : %s%n", eGrave);
byte[] bytes = eGrave.getBytes(StandardCharsets.UTF_8);
System.out.printf("UTF-8 hex : %X %X%n",
bytes[0], bytes[1], bytes[0], bytes[1]
);
System.out.printf("letter ISO-8859-1: %s%n",
new String(bytes, StandardCharsets.ISO_8859_1)
);
出力
letter UTF8 : è
UTF-8 hex : C3 A8
letter ISO-8859-1: è
私にとってフォームは正しいUTF8エンコードされたデータを送信しますが、後でこのデータはUTF8として扱われません。
編集試してみるべきその他のポイント:
リクエストの文字エンコーディングを出力する
System.out.println(request.getCharacterEncoding())
パラメータを取得するためにUTF-8の使用を強制します(テストされていない、アイデアのみ)
request.setCharacterEncoding("UTF-8");
... request.getParameter(...);
あなたはそれを.jspに書くことを試みることができます:
<%@ page language="Java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="UTF-8"%>
それで問題は解決しました。
JSPコードのcharsetおよびpageEncoding定義でISOに関連する文字列を使用できます。
Charset = "ISO-8859-1"やpageEncoding = "ISO-8859-1"と同様です。
Tomcatには、あなたを引っ掛かるバグがあります。最初のフィルターは、要求が基づくエンコーディングを定義します。
最初のフィルターの背後にある他のすべてのフィルターまたはサーブレットは、要求のエンコーディングを変更できなくなります。
現在のアプリケーションはエンコーディングに依存している可能性があるため、このバグは将来修正されるとは思いません。