У меня возникла своеобразная проблема. Мой сервлет получает строку с urlencoded, и из журнала я могу сказать, что эта строка верна.java.net.URLDecoder зависит от кодировки исходного файла?
Я попытался с этой строкой:
"test+%F0%9F%98%8E+1+%E2%99%A7+%E2%99%A2+%E2%99%A1+%E2%99%A4+%E3%80%8A"
, который является следующим:
"test 1 ♧ ♢ ♡ ♤ 《"
Однако, когда я запускаю тест, я получаю тот же результат, как я получаю на моем сервере:
"test ? 1 ? ? ? ? ?"
Сброс шестнадцатеричных кодов Я получаю
00: 74 65 73 74 20 3F 20 31 20 3F 20 3F 20 3F 20 3F | test ? 1 ? ? ? ?
10: 20 3F -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ?
Где я ожидал:
00: 74 65 73 74 20 F0 9F 98 8E 20 31 20 E2 99 A7 20 | test ... . 1 ...
10: E2 99 A2 20 E2 99 A1 20 E2 99 A4 20 E3 80 8A -- | ... ... ... ...
Теперь для "интересной" бит. Это происходит на моем сервере и в моей Eclipse IDE, но если я затем сохраню исходный файл в UTF-8, URLDecoder вернет правильные данные! Это не помогло на моем сервере.
1: Я не вижу, как это может быть так, URLDecoder должен прослушивать запрошенную кодировку. 2: Мне явно нужна замена для java.net.URLDecoder, если он это делает, он принципиально нарушен. Какие-либо предложения?
Код испытания:
public class URLDecoderTest {
public static void main(String[] args) {
String reqMsg = "test+%F0%9F%98%8E+1+%E2%99%A7+%E2%99%A2+%E2%99%A1+%E2%99%A4+%E3%80%8A";
System.out.println("reqMsg : " + reqMsg);
try {
reqMsg = URLDecoder.decode(reqMsg, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("reqMsg : " + reqMsg);
System.out.println(HexTools.dump(reqMsg));
System.out.println("Expected (fixed):");
System.out.println("00: 74 65 73 74 20 F0 9F 98 8E 20 31 20 E2 99 A7 20 | test ... . 1 ... ");
System.out.println("10: E2 99 A2 20 E2 99 A1 20 E2 99 A4 20 E3 80 8A -- | ... ... ... ...");
}
}
Примечание: HexTools от Mobicents: http://code.google.com/p/mobicents/source/browse/trunk/commons/src/main/java/org/mobicents/commons/HexTools.java?r=21908
Edit: Глядя на источник URLDecoder.decode, он использует новый String (байт, 0, pos, enc) для декодирования байтов. По какой-то причине это не удается, но для unicode новая строка (bytes, 0, pos) работает нормально.
Есть ли ошибка в классе StringCoding Java, что она автоматически возвращается к кодировке по умолчанию, независимо от того, что ей передается? метод декодирования, вызываемый String, является статическим, и он устанавливает запрошенную кодировку другим статическим методом перед вызовом декодирования, который затем будет использовать этот статический. Другими словами: это не потокобезопасный !!!
Обновление: У меня были проблемы практически во всех слоях моих реализаций. Символ Emoji (4-байтовые символы utf-8) вызвал, например, проблемы с MySQL. Я получил от него asciified символы, даже если он был установлен в utf8.
Заключительное замечание: Часть проблемы или предполагаемой проблемы действительно, было вызвано злоупотреблением HexTools.dump (String), класс построен для обработки двоичных данных, где символы даже струны только содержащиеся на нем данные в низких байт.
Для справок в будущем обращайтесь к HexTools.свалка должна быть:
System.out.println(HexTools.dump(reqMsg.getBytes("UTF-8")));
с фиксирующим блоком для UnsupportedEncodingException съехал, чтобы покрыть эту линию курса. Выполнение этого, возвращает шестнадцатеричный кадр, идентичный ожидаемому.
Где-то вдоль линии ваши данные преобразуются в ASCII. –
Единственное место, которое может произойти, находится внутри java.net.URLDecoder, оно не должно. –
Мне не хватает опыта работы с java.net, чтобы помочь вам больше, но это похоже на поведение преобразования utf8 в ASCII. –