Русский язык, вызывающий исключение ввода-вывода

#java #json #telegram #telegram-bot

#java #json #telegram #telegram-бот

Вопрос:

Я создаю бота для словаря Google, используя этот APIhttps://dictionaryapi.dev /. Предполагается, что он показывает определения слов на разных языках. И бот отлично работает для английского и испанского языков. Но каждый раз, когда я вставляю русские слова, возникает исключение IOException. Что может быть причиной этого?

Вот мой класс Bot. Bot.java:

 public void onUpdateReceived(Update update) {
        //Model model = new Model();
        WordModel wordModel = new WordModel();
        Message message = update.getMessage();
        if (message != null amp;amp; message.hasText())
        {
            switch (message.getText()) {
                case "/english":
                    DictionaryEntry.setLanguage("en");
                    sendMsg(message, DictionaryEntry.getLanguage());
                    break;
                case "/russian":
                    DictionaryEntry.setLanguage("ru");
                    sendMsg(message, DictionaryEntry.getLanguage());
                    break;
                case "/spanish":
                    DictionaryEntry.setLanguage("es");
                    sendMsg(message, DictionaryEntry.getLanguage());
                    break;
                default:
                    if (!message.getText().contains("/")) {
                        try {
                            sendMsgs(message, DictionaryEntry.getWords(message.getText(), wordModel));
                        } catch (IOException e) {
                            sendMsg(message, "Не найдено");
                            sendMsg(message, DictionaryEntry.getUrl().toString());
                        }
                    }
                    break;
            }
        }
    }

public void sendMsg(Message message, String text) {
        SendMessage sendMessage = new SendMessage();
        sendMessage.setChatId(message.getChatId());
        sendMessage.setReplyToMessageId(message.getMessageId());
        sendMessage.setText(text);
        try {
            //setButtons(sendMessage);
            execute(sendMessage);
        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }

public void sendMsgs(Message message, List<String> words) {
        for (int i = 0; i < words.size(); i  ) {
            SendMessage sendMessage = new SendMessage();
            sendMessage.setChatId(message.getChatId());
            sendMessage.setReplyToMessageId(message.getMessageId());
            sendMessage.setText(words.get(i));
            try {
                //setButtons(sendMessage);
                execute(sendMessage);
            } catch (TelegramApiException e) {
                e.printStackTrace();
            }
        }
    }
  

И вот мой класс DictionaryEntry, в котором я обрабатываю строку JSON, которую я получаю из URL.
DictionaryEntry.java:

 private static String language = "ru";

    public static String getLanguage() {
        return language;
    }

    public static void setLanguage(String language) {
        DictionaryEntry.language = language;
    }

    public static URL getUrl() {
        return url;
    }

    private static URL url;

public static List<String> getWords(String message, WordModel wordModel) throws IOException {
        url = new URL("https://api.dictionaryapi.dev/api/v2/entries/"
                  DictionaryEntry.getLanguage()   "/"   message);

        Scanner in = new Scanner((InputStream) url.getContent());
        String result = "";

        while (in.hasNext())
        {
            result  = in.nextLine();
        }

        String result2 = result.replaceAll(""", "\"");

        List<WordModel> models = new ArrayList<>();
        List<String> results = new ArrayList<>();
        int count = 0;

        try {
            JSONArray mainArray = new JSONArray(result2);

            for (int i = 0; i < mainArray.length(); i  ) {
                JSONObject wordEntry = mainArray.getJSONObject(i);
                String wordName = wordEntry.getString("word");
                wordModel.setWord(wordName);

                JSONArray meaningsArray = wordEntry.getJSONArray("meanings");
                for (int j = 0; j < meaningsArray.length(); j  ) {
                    JSONObject meaningEntry = meaningsArray.getJSONObject(j);
                    JSONArray definitionsArray = meaningEntry.getJSONArray("definitions");
                    for (int k = 0; k < definitionsArray.length(); k  ) {
                        //count  ;
                        JSONObject definitionEntry = definitionsArray.getJSONObject(k);
                        String definition = definitionEntry.getString("definition");
                        wordModel.setDefinition(definition);

                        if (definitionEntry.has("example")) {
                            count  ;
                            String example = definitionEntry.getString("example");
                            wordModel.setExample(example);
                        }
                        else {
                            wordModel.setExample("No examples found");
                        }

                        models.add(wordModel);
                        results.add("Word: "   wordModel.getWord()   "nn"  
                                "Definition: "   wordModel.getDefinition()   "nn"  
                                "Example: "   wordModel.getExample());
                    }
                }
            }

            /*result = "Word: "   wordModel.getWord()   "nn"  
                     "Definition: "   wordModel.getDefinition()   "nn"  
                     "Example: "   wordModel.getExample();*/
        } catch (JSONException e) {
            count = 50;
        }

        results.add(url.toString());

        return results;
    }
  

Вот трассировка стека:

 java.io.IOException: Server returned HTTP response code: 400 for URL: https://api.dictionaryapi.dev/api/v2/entries/ru/мышь
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1932)
    at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1528)
    at java.base/java.net.URLConnection.getContent(URLConnection.java:749)
    at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getContent(HttpsURLConnectionImpl.java:404)
    at java.base/java.net.URL.getContent(URL.java:1181)
    at DictionaryEntry.getWords(DictionaryEntry.java:73)
    at Bot.onUpdateReceived(Bot.java:91)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.telegram.telegrambots.meta.generics.LongPollingBot.onUpdatesReceived(LongPollingBot.java:27)
    at org.telegram.telegrambots.updatesreceivers.DefaultBotSession$HandlerThread.run(DefaultBotSession.java:321)
  

Комментарии:

1. Вы проверили сообщение внутри исключения? Он может содержать некоторую полезную информацию.

2. Что говорит исключение IOException? Показать сообщение и трассировку стека.

3. Добавлена трассировка стека

4. Что ж, похоже, что вызываемому вами серверу не нравятся символы кириллицы в URL

5. @BiT4000 может быть нормально кодировать только message значение переменной.

Ответ №1:

   URLEncoder.encode(message, "UTF-8")
  

Вы отправляете HTTP-запрос. URL-адрес должен соответствовать используемой кодировке.

Есть и другие аспекты использования правильной кодировки, но этого может быть уже достаточно. Сайт, вероятно, использует UTF-8, поскольку он может обрабатывать полный диапазон Unicode.

400 — НЕВЕРНЫЙ ЗАПРОС.


 url = new URL("https://api.dictionaryapi.dev/api/v2/entries/"
              DictionaryEntry.getLanguage()   "/"
              URLEncoder.encode(message, "UTF-8"));
  

И

     Scanner in = new Scanner((InputStream) url.getContent(),
        StandardCharsets.UTF_8);
    StringBuilder sb = new StringBuilder();
    while (in.hasNextLine())
    {
        sb.append(in.nextLine()).append('n');
    }
    String result = sb.toString();
  

Комментарии:

1. Что именно я должен кодировать? Каким здесь должно быть «сообщение»? Мой URL?

2. Хорошо, проверил код. StringBuilder вместо цикла со строкой = , даже если здесь можно ожидать не так много строк. result = "rn"; забыто.

3. Я закодировал слово на русском, которое я отправляю. Теперь это работает. Спасибо, что нашли время.

Ответ №2:

Проверьте в своей среде, что файл был в формате utf-8u, поскольку кириллица может не поддерживаться

Комментарии:

1. Как это сделать?

2. Пожалуйста, добавьте такого рода уточняющие идеи в качестве комментариев. Это не является ответом, решающим проблему, с которой сталкивается OP.

3. @BiT4000 Если вы работаете в Intellij: Файл -> Настройки -> Редактор -> Кодировки файлов