Я пытаюсь прочитать ответ с URL-адреса, отправляющего тело JSON. Но мой код не может прочитать полный ответ. В моем коде есть проблема, но я этого не понимаю.
val url: URL = new URL("https://jsonplaceholder.typicode.com/todos/1")
val httpsConnection: HttpsURLConnection = url.openConnection().asInstanceOf[HttpsURLConnection]
httpsConnection.setRequestMethod("GET")
httpsConnection.setRequestProperty("Accept", "application/json")
httpsConnection.setRequestProperty("Accept-Language", "en_US")
val streamReader: InputStreamReader = new InputStreamReader(httpsConnection.getInputStream)
val bufferedReader = new BufferedReader(streamReader)
val stringBuffer: StringBuffer =new StringBuffer()
while(bufferedReader.readLine() != null){
stringBuffer.append(bufferedReader.readLine())
}
println(stringBuffer.toString)
Этот приведенный выше код не дает мне фактического результата. Но если я избегаю обычного стиля Java и использую исходный код scala:
Source.fromInputStream(httpsConnection.getInputStream,"UTF8").getLines().foreach(println)
это дает фактический JSON.
В чем проблема в моем первом разделе кодов?
@niekname, я теряю данные в цикле while, если я проверяю строку с нулевым значением, я теряю данные, если также проверяю bufferedReader.read() != -1.
Каково содержание данных, которые вы ожидаете получить? Вот что я получаю, когда запускаю ваш код: ""userId": 1, "title": "delectus aut autem",}"
Цикл while тратит впустую чтение строки. Может быть, сделать что-то вроде while (true) { String line = bufferedReader.readLineI(); если (строка == ноль) перерыв; строкаBuffer.append (строка); }
@Matthew Я ожидаю { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false}
Хорошо, мой ответ даст вам именно это, но требует внешних библиотек, которые вы должны использовать для таких сложных задач в целом. Это устранит обычные предостережения, которые случаются в таких ситуациях.
Я знаю, что это не совсем то, что вы ищете, но манипулирование данными иногда может быть довольно сложным, особенно когда вы используете сети. Поэтому в интересах простоты я бы рекомендовал использовать внешние библиотеки для чтения файла JSON
из URL
.
Следующий код извлекает ваш файл JSON
по предоставленной вами ссылке, используя методы, предоставленные JSON.простой и Apache Commons IO:
public void getJson() throws IOException {
java.net.URL url = new java.net.URL("https://jsonplaceholder.typicode.com/todos/1");
String json = IOUtils.toString(url, Charset.forName("UTF-8"));
System.out.println(json);
}
В этом месте:
while(bufferedReader.readLine() != null){
stringBuffer.append(bufferedReader.readLine())
}
сначала вы вызываете readLine
дважды, чтобы проверить, не является ли оно нулевым, а затем добавить к stringBuffer
. Но на самом деле второй вызов получает другую линию, так что вы теряете каждую вторую строку.
Обычный способ чтения буферизованного потока в Java:
String line;
while ((line = r.readLine()) != null) {
// do your stuff...
}
но присваивания в Scala возвращают Unit
, так что это не сработает.
Так что, может быть, стоит использовать Stream.continually
?
Stream
.continually(bufferedReader.readLine())
.takeWhile(_ != null)
.foreach(stringBuffer.append)
readLine вызывается дважды, и InputStreamReader должен использовать кодировку источника. Здесь я взял ISO-8859-1, так как он не выдаст ошибку, как UTF-8. Также readLine отбрасывает окончание строки, а StringBuilder работает быстрее.
val streamReader: InputStreamReader = new InputStreamReader(httpsConnection.getInputStream,
"ISO-8859-1")
val bufferedReader = new BufferedReader(streamReader)
val stringBuilder: StringBuilder = new StringBuilder()
while (true) {
val line = bufferedReader.readLine();
if (line == null) {
break;
}
stringBuilder.append(line).append("\r\n");
}
вы не теряете данные, потому что читаете строки в цикле while и ничего с ними не делаете?