Недавно разработанная проблема с кодировкой в ​​программе Oracle Java

Моя Java-программа (точнее, ее часть) отправляет запрос веб-сервису и получает rdf-строки, включающие древнегреческие слова в юникоде. Я написал программу в netbeans, и до сих пор не было проблем во время выполнения, как в среде netbeans, так и вне ее в виде отдельного jar-файла под Linux и Windows XP. Теперь внезапно греческие слова в rdf возвращаются в таком искаженном виде:

á¼€

Сначала я подумал, что это проблема Windows XP, но при проверке под Windows 7 проблема сохранилась. Я узнал, что запускаю OpenJDK под Linux, и с тех пор смог воспроизвести проблему с помощью Oracle Java. Это соответствующий код (конечно, у меня может быть туннельное зрение, поэтому, пожалуйста, сообщите мне, если вам нужно больше):

try {
        HttpClient client = new DefaultHttpClient();
        HttpGet get;
        get = new HttpGet(URL+URLEncoder.encode(form, "UTF-8"));

        HttpResponse response = client.execute(get);
        if (201 == response.getStatusLine().getStatusCode()) {
            HttpEntity respEnt = response.getEntity();
            BufferedReader reader = new BufferedReader(new InputStreamReader(respEnt.getContent()));
            StringBuilder sb = new StringBuilder();
            char[] cbuffer = new char[256];
            int read;

            while ((read = reader.read(cbuffer)) != -1) {
                sb.append(cbuffer,0,read);
            }
            //System.out.println(sb.toString());
            rdf = new String(sb.toString().getBytes("UTF-8"),"UTF-8");

        } else {
            System.err.println("HTTP Request fehlgeschlagen.");
        }         

    } catch (IOException e) {
        System.err.println("Problem beim HTTP Request.");
    }

Веб-сервис — это сервис морфологии Perseus, его можно найти здесь: http://services.perseids.org/bsp/morphologyservice/analysis/word?lang=grc&engine=morpheusgrc&word=. Попробуйте, например, "word=μῆνιν". Как и когда генерируется rdf, я действительно не знаю.

Буду очень благодарна за дальнейшую информацию!


person user3627489    schedule 12.05.2014    source источник
comment
Когда вы заметили, что это происходит? Я думал, что XP в последнее время не получал никаких обновлений, за исключением того обновления безопасности IE. Это происходит с другими версиями Windows?   -  person awksp    schedule 12.05.2014
comment
Впервые я заметил это 4 апреля, то есть как раз перед окончанием жизненного цикла XP. Я пытался решить это самостоятельно в течение последнего месяца или около того. К сожалению, других версий Windows под рукой нет!   -  person user3627489    schedule 12.05.2014
comment
Ах я вижу. Вы пытались возиться с кодировками и посмотреть, сможете ли вы получить что-то кроме тарабарщины? И проверили ли вы, что байты, которые вы получаете с сервера, одинаковы на всех машинах, которые вы пробовали? Кроме того, если вы готовы доверять незнакомцу из Интернета, я могу попробовать ваш код на Windows 7 сегодня позже.   -  person awksp    schedule 12.05.2014
comment
Я получаю другие вещи, кроме тарабарщины, остальная часть строки rdf в порядке. Как мне проверить байты? Как вы думаете, они меняются в зависимости от того, откуда они называются? Спасибо за предложение попробовать код, однако завтра я смогу проверить компьютер с Windows 7 с коллегой!   -  person user3627489    schedule 12.05.2014
comment
О, так это просто греческий перепутался? Вы можете проверить байты, используя BufferedInputStream и [read()](docs.oracle.com/javase/7/docs/api/java/io/, int, int)) для чтения в массив байтов, который вы Затем можно распечатать, чтобы увидеть, что именно вы получаете. Я не совсем уверен, изменится ли то, что вы получите в ответ, в зависимости от машины, с которой вы получите ответ, но таким образом вы можете, по крайней мере, быть уверены, что если сообщение, которое вы получаете, одно и то же, то это не сервер делает что-то шаткое. . Хотя я бы не назвал это необходимым шагом.   -  person awksp    schedule 12.05.2014
comment
Я сомневаюсь, что байты будут значительно отличаться, если остальная часть строки в порядке и если сервер не различает машины (в большинстве случаев, я полагаю, это не так, поскольку все, что он видит, это HTTP-запрос и нет никакой информации о происхождении запроса (я думаю)). Не могли бы вы попробовать вторую машину с XP, если у вас есть к ней доступ? Делали ли вы какие-либо обновления программного обеспечения в то время?   -  person awksp    schedule 12.05.2014
comment
Есть эта страница, но она показывает только те обновления безопасности, которые мне не нужны. не думаю, что это повлияет на отображение персонажа...   -  person awksp    schedule 12.05.2014
comment
Большое спасибо за ваш вклад! Я провел дополнительную проверку и действительно столкнулся с той же проблемой в Windows 7. Затем я, наконец, вспомнил, что Ubuntu запускает OpenJDK по умолчанию, и смог воспроизвести проблему в Linux при использовании Oracle Java. Однако это становится странным: в какой-то момент во время выполнения вывод снова стал четким, и при следующем запуске программы не было никакой тарабарщины. Теперь я прочь, чтобы сделать дальнейшие тесты на Windows XP.   -  person user3627489    schedule 13.05.2014
comment
Интересно... Так что, возможно, это похоже на что-то со средой выполнения Oracle? Однако выход, меняющийся от одного прогона к другому, кажется довольно странным. Вы уверены, что сервер каждый раз возвращает один и тот же ответ? Сама среда выполнения, производящая два разных вывода при двух последовательных запусках, не кажется такой возможной для программы, поскольку программы должны работать детерминировано...   -  person awksp    schedule 13.05.2014
comment
Итак... Сейчас я попытался запустить программу под Windows с версиями Java 7_55,7_51 и 7_45, но пока никаких изменений. В настоящее время я в растерянности и, вероятно, должен снова просмотреть свой код.   -  person user3627489    schedule 14.05.2014
comment
не могли бы вы предоставить более подробную информацию о стороне сервера, пожалуйста: * Откуда он читает rdf-строки? (скажем, файлы, база данных или генерируются на лету)   -  person ithofm    schedule 15.05.2014
comment
И не могли бы вы опубликовать метод веб-сервиса, который отправляет ответ?   -  person ithofm    schedule 15.05.2014


Ответы (1)


Убедитесь, что кодировка ваших строк одинакова от клиента к серверу и обратно. В вашем случае, конечно, ответ сервера (rdf-строки) наиболее важен (кодирование на стороне сервера, декодирование в вашем клиентском коде).

Одна вещь, касающаяся клиентского кода, который вы разместили: вы используете конструктор с одним аргументом InputStreamReader в этой строке:

BufferedReader reader = new BufferedReader(new InputStreamReader(respEnt.getContent()));

Он будет считывать из входного потока с использованием кодировки по умолчанию для виртуальной машины (и системы), поэтому результат будет зависеть от машины / виртуальной машины, на которой вы запускаете свое клиентское приложение. Попробуйте явно установить кодировку с помощью этого конструктора

new InputStreamReader(url.openStream(), "UTF-8")

См. также API-doc.

Найдите в своем коде дополнительные варианты использования конструктора с одним аргументом как InputStreamReader, так и OutputStreamWriter, которые также используют кодировку по умолчанию.

Если у вас нет контроля над кодом сервера (реализация веб-сервиса), вы можете попытаться узнать кодировку ответов следующим образом:

Header contentType = response.getFirstHeader("Content-Type");
String charset= contentType.getValue();

(Это из API-интерфейса apache HttpClient, который вы, похоже, используете). см. также этот вопрос на SO.

person ithofm    schedule 14.05.2014
comment
Я не думал об этом ... Отличается ли кодировка по умолчанию между реализацией OpenJDK и Oracle? - person awksp; 14.05.2014
comment
@user3580294 user3580294 локаль может быть установлена ​​пользователем на каждом компьютере, эта локаль будет определять кодировку по умолчанию, используемую системой. - person RossBille; 15.05.2014
comment
@RossBille Я знаю об этом, но, учитывая проблемы, с которыми сталкивается OP, я не совсем уверен, что это проблема. Похоже, что программа работала в Windows, пока что-то не сломало ее некоторое время назад, и, насколько я знаю, Windows не меняет свою кодировку по умолчанию случайным образом. Не говоря уже о комментарии OP, где вывод программы менялся от запуска к запуску, но это может быть аномалией... - person awksp; 15.05.2014
comment
@user3580294 user3580294 изменение реализации JDK потенциально может повлиять на многие вещи на разных уровнях, я думаю. На первый взгляд кажется, что оба импла подбирают кодировку и кодировку по умолчанию из ОС, и на них могут влиять системные свойства, например. -Dfile.encoding. - person ithofm; 15.05.2014
comment
@ithofm Я полагаю ... Думаю, нам придется посмотреть, решит ли это проблему ОП. Есть еще несколько вещей, которые я нахожу странными, например, то, как разные запуски программы дают разные результаты, которые заставляют меня думать, что кодирование может быть не проблемой (или не единственной проблемой)... - person awksp; 15.05.2014
comment
Явный InputStreamReader действительно решил проблему, большое спасибо! Похоже, что веб-служба что-то изменила, в этом смысле они немного ненадежны (я добавляю это к вопросу для дальнейшего использования). Однако аномалия под Linux остается загадкой: мне не удалось воспроизвести искаженный вывод, и каждый раз, когда я запускаю программу, все одно и то же. На данный момент я готов оставить это, так как люди, использующие программу, запускают ее под Windows. В любом случае, большое спасибо всем вам! - person user3627489; 17.05.2014