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

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

public void onUpdateReceived(Update update) {
        //Model model = new Model();
        WordModel wordModel = new WordModel();
        Message message = update.getMessage();
        if (message != null && 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() + "\n\n" +
                                "Definition: " + wordModel.getDefinition() + "\n\n" +
                                "Example: " + wordModel.getExample());
                    }
                }
            }

            /*result = "Word: " + wordModel.getWord() + "\n\n" +
                     "Definition: " + wordModel.getDefinition() + "\n\n" +
                     "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)
0
BiT4000 14 Сен 2020 в 13:27

2 ответа

Лучший ответ
+ 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
Joop Eggen 14 Сен 2020 в 13:01

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

0
Андрій Котюга 14 Сен 2020 в 10:37