Есть Tomcat 8 + сервлеты, IDE - Eclipse, ОС - Debian 9. Из сервлетов посылаю GET-запрос на удаленный сервер (указав кодировку в запросе. Предполагается, что это кодировка страницы с удаленного сервера), получаю HTML страничку, парсю ее. Странички содержат русские и украинские буквы. Проблема заключается в том, что даже не смотря на то, что в Эклипсе пришедший ответ читается нормально, отображаются русские буквы, в файл уже пишутся либо ????, либо совсем другие, страшные кракозябры.
Проблема наблюдается с двумя сайтами:
"http://www.meteo.nw.ru/weather/lo_meteod.php", "windows-1251" (исходная кодировка на сайте) и
"http://meteoinfo.ru/mosobl", "UTF-8"(исходная кодировка на этом сайте)
Вот упрощенный код, пытаюсь перекодировать маленький кусочек русского текста:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
response.getWriter().println();
StringBuffer response1 = null;
String url = "http://www.meteo.nw.ru/weather/lo_meteod.php";
String encoding ="windows-1251";
URL obj = new URL(url );
HttpURLConnection connection = (HttpURLConnection) obj.openConnection();
int status =0;
int connectionCounter = 0;//не больше трех раз
try {
response.getWriter().println("Make the connection with Meteod");
do {
if(connectionCounter<3){
connection = (HttpURLConnection) obj.openConnection();
connection.setRequestMethod("GET");
if (status!= HttpURLConnection.HTTP_OK) status = connection.getResponseCode();//три раза спрашиваем, но до первого положительного ответа
else break;
}
} while (status!= HttpURLConnection.HTTP_OK);//пока не придет положительный ответ от сервера
}
catch(ConnectException e) {
System.out.println("Ошибка соединения ");
System.out.println(e.toString());
}
catch(IllegalArgumentException e) {
System.out.println("Ошибка IllegalArgumentException ");
System.out.println(e.toString());
}
catch(IOException e) {
System.out.println("Общая ошибка ");
System.out.println(e.toString());
}
try{
if(status== HttpURLConnection.HTTP_OK){//если пришел
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
String inputLine;
response1 = new StringBuffer();
while ((inputLine = in.readLine()) != null)
response1.append(inputLine);
in.close();
}
else {System.out.println("Сервер не отвечает по адресу "+url); }
}
catch(NullPointerException e) {
System.out.println("NullPointerException ");
System.out.println(e.toString());
}
catch(IOException e) {
System.out.println("Общая ошибка ");
System.out.println(e.toString());
}
String answer = response1.toString();
int ind = answer.indexOf("се");
answer = answer.substring(ind, ind+20);
response.getWriter().println("The piece of answer: "+answer);
System.out.println("Пример распарсенного ответа: "+answer);
byte[] winData = answer.getBytes("Cp1251");
String string = new String(winData,"Cp1251");
response.getWriter().println("After recoding : "+answer);
System.out.println("После перекодиовки: "+answer);
File fileMain = new File("C:" + File.separator + "Users" + File.separator + "Alena" + File.separator + "workspace" + File.separator + "AServlet" + File.separator + "test.txt");
try {
if(!fileMain.exists()){//проверяем, что если файл не существует то создаем его
fileMain.createNewFile();
response.getWriter().println("create an file "+fileMain.getAbsolutePath());
System.out.println("Создали файл " + fileMain );
}
//BufferedWriter outForMain = new BufferedWriter(new OutputStreamWriter((), "<encoding name>"));
BufferedWriter outForMain = new BufferedWriter(new FileWriter(fileMain, true));//дописывание в конец документа
try
{
response.getWriter().println("Write in file "+fileMain.getAbsolutePath());
System.out.println("Пишепм");
outForMain.append(answer);
outForMain.newLine();
} finally {
outForMain.close();
}
FileInputStream fstream = new FileInputStream(fileMain);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
try{
response.getWriter().println("Read from file "+fileMain.getAbsolutePath());
String strLine;
while ((strLine = br.readLine()) != null){
response.getWriter().println("The piece of something we read: "+strLine);
System.out.println("Прочли "+strLine);
}
} finally {
br.close();
}
}catch (IOException e){
System.out.println("Ошибка");
}
}
Ваш код за гранью добра и зла. Приложение, написанное в таком стиле, будет проклято первым человеком, кто попытается в нем что-то исправить либо изменить. Причем этот первый человек, скорее всего, вы сами. Пишите простые и короткие методы, можно использовать стандартные паттерны проектирования. Старайтесь избавиться от дублирующего кода, вынести его в отдельные методы. Это сделает код лаконичным и понятным. Кроме того, хоть иногда заглядывайте в документацию и следите за тем, какие плюшки появляются с выходом новых версий Java и что по этому поводу думают разработчики самого языка. К примеру, конструкция trywithresources появилась еще в 7 версии и ее, согласно документации, настоятельно рекомендуется использовать. А еще есть лямбды... Они тоже способны сократить код. Итого, насколько я понял проблему, у вас трудности с кодировкой при парсе указанных двух сайтов. Я написал вам простой и понятный класс. Из метода мейн сделаете метод, принимающий какие-то параметры, в зависимости от ваших интерфейсов, а дальше простым вызовом 3 методов можно спарсить сайт, записать его в текстовый файл и прочитать из текстового файла. Обратите внимание, что в моем коде для его понимания даже комментировать ничего не надо. И еще... В данном случае мы получаем просто строковую переменную, в которой содержится html страницы. его же записываем в файл, его же читаем и печатаем в консоль. Ведь в вопросе сказано, что проблема именно с кодировкой, мой код решает именно эту проблему. Ежели вам нужно парсить содержимое, то настоятельно рекомендую пользоваться общепринятыми библиотеками. Если это просто страничка HTML - Jsoup, а если нужен JSON - jackson. Обратите внимание, что в том же Jsoup получить стандартный документ для дальнейшей работы можно разными способами, в т.ч. и из обычной строковой переменной, содержащей HTML-страничку: Document document = Jsoup.parse(htmlPage). Причем для сайта есть возможность передать URL либо InputStream и это будет на много конструктивнее. Если же вам нужно вычитывать HTML - из файла, то один из уже указанных вариантов - передать InputStream , но в некоторых случаях может потребоваться передать простую строковую переменную, как я и показал. Удачи
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
class Parser {
private static final String CHARSET_CP1251 = "Cp1251";
private static final String CHARSET_UTF8 = "UTF-8";
private static final String FILE_NAME = "1.txt";
public static void main(String[] args) throws IOException {
Parser parser = new Parser();
String site = parser.parseSite("http://www.meteo.nw.ru/weather/lo_meteod.php", CHARSET_CP1251);
//String site = parseSite("http://meteoinfo.ru/mosobl", CHARSET_UTF8);
parser.writeFile(FILE_NAME, site, CHARSET_UTF8);
String readFile = parser.readFile(FILE_NAME, CHARSET_UTF8);
System.out.println(readFile);
}
private String parseSite (String url, String charset) throws IOException{
HttpURLConnection connection =(HttpURLConnection)new URL(url).openConnection();
return toStringByInputStream(new InputStreamReader(connection.getInputStream(), charset));
}
private String readFile(String fileName, String charset) throws IOException {
return toStringByInputStream(new InputStreamReader(new FileInputStream(fileName), charset));
}
private String toStringByInputStream (InputStreamReader inputStreamReader) throws IOException {
StringBuilder result = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
bufferedReader.lines().forEach((String line)->result.append(line).append("\r\n"));
}
return result.toString();
}
private void writeFile (String fileName, String text, String charset) throws IOException{
try (BufferedWriter br = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), charset))) {
br.write(text);
br.flush();
}
}
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Глядя на уроки на просторах интернета вижу, что добавляют данные в базу используя ContentValuesНо конструктора принимающего тип Date там нет
RecyclerView отображает список CardView с текстом, их можно добавлять и удалятьПроблема вот в чем, я пытаюсь реализовать изменение itema, то есть, на card view по мимо...
Как рисовать на одном Canvas из разных классов? Проблема в том, что при обращении к canvas из разных классов возвращаются разные ссылки