Мое предположение состоит в том, что вашей кодовой платформой по умолчанию была UTF-8, и возникли проблемы с кодированием. Для удаленного контента должна быть указана кодировка, и не предполагается, что она равна кодировке по умолчанию на вашем компьютере.
Кодировка данных ответа должна быть правильной. Для этого заголовки должны быть проверены. Значение по умолчанию должно быть Latin-1, ISO-8859-1, но браузеры интерпретируют это как Windows Latin-1, Cp-1252.
String charset = connection.getContentType().replace("^.*(charset=|$)", "");
if (charset.isEmpty()) {
charset = "Windows-1252"; // Windows Latin-1
}
Тогда вы можете лучше читать байты, поскольку нет точного соответствияна количество прочитанных байтов и количество прочитанных символов. Если в конце буфера находится первый символ суррогатной пары , двух символов UTF-16, которые образуют глиф Unicode, символ, кодовую точку выше U + FFFF, я не знаю эффективностилежащий в основе «ремонт».
BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead < 0) {
break;
}
if (bytesRead > 0) {
out.write(buffer, 0, bytesRead);
}
}
return out.toString(charset);
И действительно, это безопасно сделать:
sb.append(inputBuffer, 0, charsRead);
(Получение копии, вероятно, было попыткой восстановления.)
ПоКстати, char[500]
занимает почти вдвое больше памяти, чем byte[512]
.
Я видел, что сайт использует сжатие gzip в моем браузере. Это имеет смысл для текста, такого как JSON. Я имитировал его, установив заголовок запроса Accept-Encoding: gzip .
URL url = new URL("https://www.reddit.com/r/tech/top.json?limit=100");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
try (InputStream rawIn = connection.getInputStream()) {
String charset = connection.getContentType().replaceFirst("^.*?(charset=|$)", "");
if (charset.isEmpty()) {
charset = "Windows-1252"; // Windows Latin-1
}
boolean gzipped = "gzip".equals(connection.getContentEncoding());
System.out.println("gzip=" + gzipped);
try (InputStream in = gzipped ? new GZIPInputStream(rawIn)
: new BufferedInputStream(rawIn)) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead < 0) {
break;
}
if (bytesRead > 0) {
out.write(buffer, 0, bytesRead);
}
}
return out.toString(charset);
}
}
Это может быть для "браузеров", не соответствующих gzip, длиной содержимого сжатый контент был ошибочно установлен в ответе. Что является ошибкой.