Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
 Аватар для novac_33
2 / 2 / 0
Регистрация: 26.04.2016
Сообщений: 42

Кодировки в Eclipse, Windows 7, JavaFX и Ubuntu Server 14.04

08.02.2017, 20:19. Показов 3178. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Даже не знал, в какой форум задать такой вопрос. Проблема следующая. Имеется клиент-серверное приложение-мессенеджер. Для него есть консольный сервер и два клиента - консольный и GUI.
GUI клиент работает на JavaFX и принимает ввод пользователя из TextField, затем через println от PrintWriter отправляет на сервер. Читает с сервера через BufferedReader readLine().
Консольный клиент принимает ввод пользователя через Scanner, через println от PrintWriter отправляет на сервер, и читает с него через BufferedReader readLine();
Сервер работает абсолютно так же.

Ситуации:

Русское сообщение из GUI интерпретируется сервером консоли Windows 7 без ошибок, отправляется всем пользователям без ошибок.
Русское сообщение из консольного клиента, открытого в консоли Eclipse - так же.

Русское сообщение из консольного клиента Windows 7 оставляет символы, довольно непримелимые для мессенеджера - ЏаЁўҐв. Так как сервер понимает его с ошибкой, то и все остальные понимают с ошибкой.

Русское сообщение отовсюду интерпретируется консольным сервером Ubuntu 14.04 с ошибками, выдаёт просто ?????? всюду.

Я понимаю, что при выводе или вводе с консоли будет биться кодировка, но почему при передаче она бьется? Или я неправильно выбрал потоки для ввода и вывода с сокета?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.02.2017, 20:19
Ответы с готовыми решениями:

Проект JavaFX в Eclipse не видит библиотеки из javafx-sdk
Доброго всем времни суток. Помогите решить вот такую проблемку. Установил среду Eclipse. В ней установил через Marketplace...

Ubuntu Server 18.04 + Windows server 2012 R2 как добавить загрузку последней через Grub-Customizer
Здравствуйте! Есть 2 образа ОС, сделанные Акронисом: Ubuntu Server 18.04 и Windows server 2012 R2. Решил установить их на один SSD 450...

Запустить проект собранный в eclipse на ubuntu в windows
С помощью IDE Eclipse C++ создал проект. Слышал, что то, что собрано в unix системах, можно запустить в windows. Вот такие файлы...

10
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
08.02.2017, 21:46
novac_33, у тебя две точки, где может играть роль кодировка: сокет и клиентский интерфейс.

С сокетом всё просто:
1) можно вообще не париться насчёт кодировок и использовать массивы байт и InputStream/OutputStream
2) если хочется использовать всякие writer'ы, то достаточно использовать на клиенте и сервере одну и ту же кодировку (лучше UTF-8, она наиболее распространена в «сети», поэтому будет оптимальным решением), важно только не забывать её указывать в конструкторах Reader'ов и Writer'ов (ЕМНИП, не все реализации интерфейсов Reader и Writer позволяют указывать кодировку, InputStreamReader и OutputStreamWriter точно умеют, их можно использовать как прослойки).

А вот с клиентами всё интересней: cmd.exe поумолчанию использует кодировку cp866, JVM же поумолчанию под виндой ожидает cp1251, соответственно нужно либо в cmd.exe поменять кодировку (и, возможно, шрифт) командой «chcp 1251» (или сразу на юникод chcp 65001 или как-то так, но тогда и в джавопрограмме это надо будет учитывать), либо учитывать это в программе.
Ну или забить на консольный клиент и использовать только гуёвый.

Не по теме:

В общем, с виндой, как всегда, геморрой =)

1
 Аватар для novac_33
2 / 2 / 0
Регистрация: 26.04.2016
Сообщений: 42
09.02.2017, 04:19  [ТС]
korvin_, сделал так: сервер определяет через String sys = System.getProperty("os.name") систему (как закончу - к серверу можно будет аргументом дописывать желаемую кодировку). Если винда - ставит в константу "CP866". Иначе - UTF-8. Клиенты при подключении к серверу получают эту константу, и их потоки инициализируются через неё. Работает со всеми GUI/Консольными на Винде, со всеми GUI с сервером на Линуксе. Дальше проблемы:

JavaFX, вроде как, умеет читать UTF-8, а вот консоль нет. Scanner вылетает и дает null BufferedReader, когда я инициализирую их с UTF-8 (кстати, как его правильно строкой задавать? Я из java.nio.charset.StandardCharsets импортирую)/ Да, причём Scanner выбрасывает исключение только если консоль в режиме utf-8 (chcp 65001). Да, только с русской раскладкой. Что за волшебство?

Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.io.*;
import java.util.Scanner;
import java.nio.charset.StandardCharsets;
public class OSEncoding {
 
    public static void main(String[] args) throws IOException {
        String name =System.getProperty("os.name");
        String vers =System.getProperty("os.version");
        String code="utf-8";
        if (name.contains("Windows")) {
            System.out.println("Using windows");
            //code = StandardCharsets.UTF_8;
        }
        else code = "1";
        
        PrintWriter out = new PrintWriter (
                new OutputStreamWriter( System.out, StandardCharsets.UTF_8 ),
                true
        );
        
        InputStreamReader isr = new InputStreamReader(System.in, StandardCharsets.UTF_8);
        BufferedReader in = new BufferedReader(isr);
        
        Scanner sc = new Scanner(System.in,code);
        String test2 = sc.nextLine();
        String test = in.readLine();
        out.println(test);
        out.println(test2);
    }
}

Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
D:\код\java>java OSEncoding
Using windows
Привет
Пока
я┐╜укая┐╜я┐╜я┐╜
я┐╜ривя┐╜я┐╜
 
D:\код\java>chcp 65001
Active code page: 65001
 
D:\код\java>java OSEncoding
Using windows
привет
Exception in thread "main" java.util.NoSuchElementException: No line found
        at java.util.Scanner.nextLine(Unknown Source)
        at OSEncoding.main(OSEncoding.java:25)
 
//а это уже без сканнера, BufferedReader
D:\код\java>java OSEncoding
Using windows
Привет
null


А ещё в Линуксе у меня сплошные ?????, но это не бьет конечное сообщение.
И ещё вопрос по кодировкам - это сильно плохо, что я в Винде CP866 ставлю даже на GUI, или она ничего на латинице не задевает и нормально будет всё?
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
09.02.2017, 11:58
зачем такие сложности и путаницы?
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
 
public class OSEncoding {
 
    public static void main(String[] args) throws IOException {
        String name = System.getProperty("os.name");
        Charset code;
        if (name.contains("Windows")) {
            System.out.println("Using windows");
            code = Charset.forName("cp866");
        }
        else {
            code = StandardCharsets.UTF_8;
        }
 
        PrintWriter out = new PrintWriter (
                new OutputStreamWriter( System.out, code),
                true
        );
 
        InputStreamReader isr = new InputStreamReader(System.in, code);
 
        Scanner sc = new Scanner(isr);
        String test = sc.nextLine();
        out.println(test);
    }
}
1
 Аватар для novac_33
2 / 2 / 0
Регистрация: 26.04.2016
Сообщений: 42
09.02.2017, 12:22  [ТС]
LeX, так у меня работает сервер. Но если он на UTF-8, а консоль на CP866, то консоль отобразит сообщение с сервера некорректно, и сама ничего не передаст нормального. Поэтому я клиент переключаю на кодировку в зависимости от сервера. Небольшая проблема ещё в том, что JavaFX, похоже, умеет отображать любые кодировки, а консоли нет. Поэтому пользователю придется переключить свою консоль в ту же кодировку, что и сервер. Ну, для консольного клиента. Но это проще, чем кодировать сообщение в двух кодировках и от клиента узнавать его кодировку и передавать нужный ему набор байт. Консольным клиентом, по идее, пользоваться будут знающие люди (ну и там ридми напишу).
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
09.02.2017, 13:08
Лучший ответ Сообщение было отмечено novac_33 как решение

Решение

так отправляй и читай данные сокета в UTF8 как на сервере, так и на клиенте, а с консоли под виндой читай как в моем примере, главное из стрима считать с указанием кодировки в которой там идут данные, а дальше, открою тебе вселенскую тайну, все строки в рантайме (в объекте типа String) всегда лежат в UTF8

Добавлено через 2 минуты
учись гуглить

Добавлено через 2 минуты
вот тебе подтверждение:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
 
public class OSEncoding {
 
    public static void main(String[] args) throws IOException {
        String text = "блабла";
        String name = System.getProperty("os.name");
        Charset code;
        if (name.contains("Windows")) {
            System.out.println("Using windows");
            code = Charset.forName("cp866");
        } else {
            code = StandardCharsets.UTF_8;
        }
 
        PrintWriter out = new PrintWriter (
                new OutputStreamWriter( System.out, code),
                true
        );
 
        InputStreamReader isr = new InputStreamReader(System.in, code);
 
        Scanner sc = new Scanner(isr);
        String test = sc.nextLine();
        out.println(test);
        printBytes(out,test.getBytes());
        printBytes(out,test.getBytes("UTF8"));
        printBytes(out,test.getBytes("cp866"));
        printBytes(out,text.getBytes());
        printBytes(out,text.getBytes("UTF8"));
        printBytes(out,text.getBytes("cp866"));
    }
    
    private static void printBytes(PrintWriter out, byte[] bytes) {
        for(byte b: bytes) {
            out.printf("%02x", b);
        }
        out.println();
    }
}
консольный вывод:
> java OSEncoding
Using windows
йцукен
йцукен
d0b9d186d183d0bad0b5d0bd
d0b9d186d183d0bad0b5d0bd
a9e6e3aaa5ad
d0b1d0bbd0b0d0b1d0bbd0b0
d0b1d0bbd0b0d0b1d0bbd0b0
a1aba0a1aba0
консольный вывод когда code - всегда UTF8
йцукен
я┐╜я┐╜укея┐╜
efbfbdefbfbde3aaa5efbfbd
efbfbdefbfbde3aaa5efbfbd
3f3f3f3f
d0b1d0bbd0b0d0b1d0bbd0b0
d0b1d0bbd0b0d0b1d0bbd0b0
a1aba0a1aba0
1
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
09.02.2017, 18:54
Цитата Сообщение от LeX Посмотреть сообщение
все строки в рантайме (в объекте типа String) всегда лежат в UTF16
Obvious FIX. =)
1
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
09.02.2017, 19:02
korvin_, да, точно)
1
 Аватар для novac_33
2 / 2 / 0
Регистрация: 26.04.2016
Сообщений: 42
10.02.2017, 03:35  [ТС]
Так, а почему строка 11 выдает корректный ответ, даже если консоль не переключена в UTF?

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class OSEncoding {
 
    public static void main(String[] args) throws IOException {
 
        InputStreamReader isr = new InputStreamReader(System.in, "CP866"); //Пишем сообщение в CP866
        Scanner sc = new Scanner(isr);
        String s = sc.nextLine();
        
        byte[] message = s.getBytes("UTF-8"); //кодируем в UTF8 байты то, что написано в CP866
        String mes = new String(message,"UTF-8");//Создаем сообщение в кодировке UTF-8
        System.out.println("UTF8: "+mes);//Показываем сообщение в UTF-8
        
        byte[] decode = mes.getBytes("CP866");//Кодируем в CP866
        String answer = new String(decode,"CP866");//Создаем CP866 строку
        System.out.print("CP866: "+answer); //выдаем ответ
        
    }
}
0
Эксперт Java
378 / 370 / 114
Регистрация: 30.06.2010
Сообщений: 1,445
10.02.2017, 05:33
В 7 строке ты получаешь String объект в кодировке UTF16, в 9 строке ты получаешь массив байт в кодировке UTF8, в 10 строке опять получаешь строку в UTF16 из массива байт, указав при этом что он в UTF8(указываешь как декодировать). В 13 и 14 строке тоже самое, только не UTF8, а cp866
1
 Аватар для novac_33
2 / 2 / 0
Регистрация: 26.04.2016
Сообщений: 42
10.02.2017, 23:16  [ТС]
LeX, а при выводе на консоль через поток с указаной кодировкой любая строка сама в неё переходит, или нужно перегнать её в байты с такой кодировкой, а потом обратно в строку с кодировкой потока?

Добавлено через 2 часа 20 минут
В итоге сделал следующее:
Для консолей на Windows автоматически ставлю кодировку "CP866" для Scanner, которым ввожу сообщения, через поток InputStreamReader. Для консолей на Linux ставлю "UTF-8", так же через InputStreamReader внутри Scanner.
Все сообщения на сервер и с сервера отправляю в кодировке UTF-8, никаких промежуточных перекодирований не потребовалось. Работает на всём.
Спасибо за помощь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.02.2017, 23:16
Помогаю со студенческими работами здесь

Ubuntu server 12.04 и Windows XP
Доброго времени суток уважаемые пользователи! Пришел к Вам с вопросом, ситуация следующая: имеется windows xp и ubuntu server 12.04...

Cеть Windows Ubuntu server
Всем доброе время суток! В администрировании я новичок поэтому ищу совет у вас) Дело такое: нашёл я в кладовке старый комп на tusl2-c...

Ubuntu в домен windows server 2008
Привет всем. Не могу никак вогнать ubuntu в домен винды2008, постоянно одна и та же ошибка, пробовал разные гайды, перечитал кучу форумов,...

Тонель между ubuntu и windows server 2003
Здравствуйте. Имеется windows server 2003 с настроенным брендмауэром. Появилась необходимость защититься проксированием от ddos атак, но...

Windows server и подключенные к нему два клиента ubuntu
Надо создать сервер и проверить его работу на двух разных системах убунту. (Я мало что понимаю пока.) Я что-то создал. Вот как это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru