Здравствуйте, Madjack, Вы писали:
M>Да я не становлюсь в позу=) Я просто проверил все на практике. Если не делать тех манипуляций с перекодировками то до сервера приходит строка в cp1251.
Тебе уже 48 раз сказали — у строк (java.lang.String) кодировка прибита гвоздями — UTF-16. Всё остальное касается только байт/ввода/вывода. Найденный тобою костыль ни разу не решение проблемы. Не там роешь.
Re[7]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Тебе перед отправкой на сервер нужно получить массив байт из строки, которую ввел пользователь, в кодировке UTF-8, правильно?
H>>String fio = field.getText(); // или что там нужно M>Здесь строка fio будет в кодировке системы. Если на винде то в cp1251. А мне нужна в utf-8. Соответственно вместо:
Нет, здесь строка будет во внутренней кодировке ява-платформы (UTF-16), но для тебя это не имеет значения.
M>String text = jtextfield1.getText(); M>bytes[] bytes = text.getBytes("utf-8"); M>String utftext = new String(bytes);
Этот код не имеет смысла. Ты получаешь строку, потом получаешь из нее массив байт в кодировке UTF-8, потом из этого массива байт снова пытаешься создать строку, но кодировку не указываешь, а значит подставляется кодировка по умолчанию, равная кодировке ОС. Для винды это windows-1251. Естественно, что ты получаешь фигню.
M>я пишу одной строчкой M>String text = jtextfield1.getText().getBytes("utf-8");
Почему String text? Вот так правильно из строки получить массив байт в кодировке utf-8:
byte[] textBytes = jtextfield1.getText().getBytes("UTF-8");
Если хочешь проверить, что все правильно, то можно создать из этого массива байт строку:
String test = new String( textBytes, "UTF-8" );
Re[6]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, Golden Wolf, Вы писали:
GW>Здравствуйте, Madjack, Вы писали:
M>>Собственно когда строка приходит на сервер то получаем все в UTF-8 за исключением большой заглавной русской буквы И. Она отображается как знак вопроса в ромбике + знак вопроса без ромбика. Никакие шаманства не катят. Подскажите как в String fio получить данные из JTextField в UTF-8 независимо от операционной системы юзера и его кодировки.
GW>А вы уверенны, что проблема ДО передачи данных на сервер? GW>Каким образом данные поступают на сервер?
Уверен абсолютно. Все неоднократно проверялось на практике прежде чем выстроить эту теорию. + Я не одинок в своей проблеме. Так как данный вопрос поднимается с 2007года на различных форумах. И именно только с буквой "И".
Данные на сервер передаются с помощью SOAP. Алгоритм следующий:
Клиент:
String text = "строка в utf-8";
String base64text = base64encode(text);
soapclient.SendText(base64text);
Как собственно выяснилась ошибка. При неизменном коде программа запускалась на MacOs и Windows. На Макинтоше проблем нет. На винде проблема с буквой И.
После получения данных от клиента на сервере делался дампфайл с пришедшими данными и затем смотрелся в браузере с изменением кодировок. С Макоса данные всегда в utf-8 с винды всегда в cp1251. после перекодировки и от туда и от туда в utf-8. но вот буква И бьется.
Затем на клиенте сделалось так:
Скажем text равен "И":
String text = jtextfield1.getText();
System.out.println(Arrays.toString(text.getBytes());
String text_u = new String(text.getBytes("utf-8");
System.out.println(Arrays.toString(text_u.getBytes());
При выводе байтов строки text байты символа были корректными
При выводе байтов строки text_u байты символов были не корректными. Вместо {-48, 104} было {-48, 64}
Re[12]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, Madjack, Вы писали:
M>>Да я не становлюсь в позу=) Я просто проверил все на практике. Если не делать тех манипуляций с перекодировками то до сервера приходит строка в cp1251. B>Логично предположить что манипуляции производятся ошибочно и решение должно быть другое.
Логично. Это и было сделано. Но результата пока нет. За этим и обращаюсь на форум.
Re[12]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И
Здравствуйте, cl-user, Вы писали:
CU>Здравствуйте, Madjack, Вы писали:
M>>Да я не становлюсь в позу=) Я просто проверил все на практике. Если не делать тех манипуляций с перекодировками то до сервера приходит строка в cp1251.
CU>Тебе уже 48 раз сказали — у строк (java.lang.String) кодировка прибита гвоздями — UTF-16. Всё остальное касается только байт/ввода/вывода. Найденный тобою костыль ни разу не решение проблемы. Не там роешь.
Я уже 48 раз ответил — помогите найти правильное решение. А если сказать нечего, кроме того что "надо найти правильное решение", то зачем спамить в топик?
Re[8]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, Donz, Вы писали:
D>Здравствуйте, Madjack, Вы писали:
D>Тебе перед отправкой на сервер нужно получить массив байт из строки, которую ввел пользователь, в кодировке UTF-8, правильно?
H>>>String fio = field.getText(); // или что там нужно M>>Здесь строка fio будет в кодировке системы. Если на винде то в cp1251. А мне нужна в utf-8. Соответственно вместо: D>Нет, здесь строка будет во внутренней кодировке ява-платформы (UTF-16), но для тебя это не имеет значения.
M>>String text = jtextfield1.getText(); M>>bytes[] bytes = text.getBytes("utf-8"); M>>String utftext = new String(bytes); D>Этот код не имеет смысла. Ты получаешь строку, потом получаешь из нее массив байт в кодировке UTF-8, потом из этого массива байт снова пытаешься создать строку, но кодировку не указываешь, а значит подставляется кодировка по умолчанию, равная кодировке ОС. Для винды это windows-1251. Естественно, что ты получаешь фигню.
M>>я пишу одной строчкой M>>String text = jtextfield1.getText().getBytes("utf-8"); D>Почему String text? Вот так правильно из строки получить массив байт в кодировке utf-8: D>byte[] textBytes = jtextfield1.getText().getBytes("UTF-8");
D>Если хочешь проверить, что все правильно, то можно создать из этого массива байт строку: D>String test = new String( textBytes, "UTF-8" );
В принципе верно. Но как теперь в SOAP у которого на входе должна быть строка отдать этот массив байт?
Re[7]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, Madjack, Вы писали:
M>Уверен абсолютно. Все неоднократно проверялось на практике прежде чем выстроить эту теорию. + Я не одинок в своей проблеме. Так как данный вопрос поднимается с 2007года на различных форумах. И именно
только с буквой "И".
Вопрос много раз поднимается не потому что актуален, а потому что многие точно так же заблуждаются.
M>Данные на сервер передаются с помощью SOAP. Алгоритм следующий:
M>Клиент: M>String text = "строка в utf-8"; M>String base64text = base64encode(text); M>soapclient.SendText(base64text);
M>Сервер: M>textutf8 = base64decode(soapserver.GetText(base64text)); M>pgsql->exec("insert into sometable (....) values (..., 'textutf8', ...);
M>Как собственно выяснилась ошибка. При неизменном коде программа запускалась на MacOs и Windows. На Макинтоше проблем нет. На винде проблема с буквой И. M>После получения данных от клиента на сервере делался дампфайл с пришедшими данными и затем смотрелся в браузере с изменением кодировок. С Макоса данные всегда в utf-8 с винды всегда в cp1251. после перекодировки и от туда и от туда в utf-8. но вот буква И бьется.
В методе base64encode должна быть указана кодировка явно. Так как у вас этого нет, то под виндой у вас используется дефолтная.
M>Затем на клиенте сделалось так: M>Скажем text равен "И": M>String text = jtextfield1.getText(); M>System.out.println(Arrays.toString(text.getBytes()); M>String text_u = new String(text.getBytes("utf-8"); M>System.out.println(Arrays.toString(text_u.getBytes());
Это попытка исправить строку, которая уже не правильно раскодирована. Данные потерялись ещё на этапе применения неправильной кодировки при раскодировании. Поэтому восстанавливать их бессмысленно.
Re[7]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, Madjack, Вы писали:
M>Я уже 48 раз ответил — помогите найти правильное решение. А если сказать нечего, кроме того что "надо найти правильное решение", то зачем спамить в топик?
что за base64encode? По-хорошему, она должна брать массив байт, а не строку. Равно как и base64decode должна возвращать массив байт (или что-то в этом роде)
Re[8]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, hrensgory, Вы писали:
H>09.03.2010 13:34, Madjack пишет:
>> Клиент: >> String text = "строка в utf-8"; >> String base64text = base64encode(text); >> soapclient.SendText(base64text);
H>А что делает base64encode (и decode на "сервере")? Скорее всего там H>что-то типа:
H>String base64encode(String str){ H> return Base64Encoder.encode(str.getBytes()); H>}
H>Если это так, то проблема понятна.
H>-- H>WBR, H>Serge.
Сервер написан на PHP. Там используются стандартные средства PHP для декодинга. а именно:
$str = base64decode($in_base64str);
Да простят меня модераторы. Выкладываю код Base64coder'а
/**
* A Base64 Encoder/Decoder.
*
* <p>
* This class is used to encode and decode data in Base64 format as described in RFC 1521.
*
* <p>
* Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br>
* Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
* Multi-licensed: EPL/LGPL/AL/BSD.
*
* <p>
* Version history:<br>
* 2003-07-22 Christian d'Heureuse (chdh): Module created.<br>
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br>
* 2006-11-21 chdh:<br>
* Method encode(String) renamed to encodeString(String).<br>
* Method decode(String) renamed to decodeString(String).<br>
* New method encode(byte[],int) added.<br>
* New method decode(String) added.<br>
* 2009-07-16: Additional licenses (EPL/AL) added.<br>
* 2009-09-16: Additional license (BSD) added.<br>
*/
public class Base64Coder {
// Mapping table from 6-bit nibbles to Base64 characters.
private static char[] map1 = new char[64];
static {
int i=0;
for (char c='A'; c<='Z'; c++) map1[i++] = c;
for (char c='a'; c<='z'; c++) map1[i++] = c;
for (char c='0'; c<='9'; c++) map1[i++] = c;
map1[i++] = '+'; map1[i++] = '/'; }
// Mapping table from Base64 characters to 6-bit nibbles.
private static byte[] map2 = new byte[128];
static {
for (int i=0; i<map2.length; i++) map2[i] = -1;
for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; }
/**
* Encodes a string into Base64 format.
* No blanks or line breaks are inserted.
* @param s a String to be encoded.
* @return A String with the Base64 encoded data.
*/
public static String encodeString (String s) {
return new String(encode(s.getBytes())); }
/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted.
* @param in an array containing the data bytes to be encoded.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode (byte[] in) {
return encode(in,in.length); }
/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted.
* @param in an array containing the data bytes to be encoded.
* @param iLen number of bytes to process in <code>in</code>.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode (byte[] in, int iLen) {
int oDataLen = (iLen*4+2)/3; // output length without padding
int oLen = ((iLen+2)/3)*4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = map1[o0];
out[op++] = map1[o1];
out[op] = op < oDataLen ? map1[o2] : '='; op++;
out[op] = op < oDataLen ? map1[o3] : '='; op++; }
return out; }
/**
* Decodes a string from Base64 format.
* @param s a Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static String decodeString (String s) {
return new String(decode(s)); }
/**
* Decodes a byte array from Base64 format.
* @param s a Base64 String to be decoded.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static byte[] decode (String s) {
return decode(s.toCharArray()); }
/**
* Decodes a byte array from Base64 format.
* No blanks or line breaks are allowed within the Base64 encoded data.
* @param in a character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static byte[] decode (char[] in) {
int iLen = in.length;
if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iLen-1] == '=') iLen--;
int oLen = (iLen*3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : 'A';
int i3 = ip < iLen ? in[ip++] : 'A';
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
int b0 = map2[i0];
int b1 = map2[i1];
int b2 = map2[i2];
int b3 = map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
int o0 = ( b0 <<2) | (b1>>>4);
int o1 = ((b1 & 0xf)<<4) | (b2>>>2);
int o2 = ((b2 & 3)<<6) | b3;
out[op++] = (byte)o0;
if (op<oLen) out[op++] = (byte)o1;
if (op<oLen) out[op++] = (byte)o2; }
return out; }
// Dummy constructor.
private Base64Coder() {}
} // end class Base64Coder
Re[14]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И
Здравствуйте, cl-user, Вы писали:
CU>Здравствуйте, Madjack, Вы писали:
M>>Я уже 48 раз ответил — помогите найти правильное решение. А если сказать нечего, кроме того что "надо найти правильное решение", то зачем спамить в топик?
CU>что за base64encode? По-хорошему, она должна брать массив байт, а не строку. Равно как и base64decode должна возвращать массив байт (или что-то в этом роде)
Как тебе и писали, проблема вот в этом:
M>/** M>* Encodes a string into Base64 format. M>* No blanks or line breaks are inserted. M>* @param s a String to be encoded. M>* @return A String with the Base64 encoded data. M>*/ M>public static String encodeString (String s) { M> return new String(encode(s.getBytes())); }
Ты должен не передавать строку, а уже сформированный массив байт в нужной тебе кодировке.
Дальше разжовывать?
Re[9]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Здравствуйте, Madjack, Вы писали:
M>В принципе верно. Но как теперь в SOAP у которого на входе должна быть строка отдать этот массив байт?
В этой теме упоминалась кодировка Base64. Полученный массив байт передаешь в функцию base64encode (или как там она называется) и получаешь строку. На другой стороне делают base64decode и получают массив байт в кодировке UTF-8, из которых создают строку
Re[10]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И
Здравствуйте, Donz, Вы писали:
D>Здравствуйте, Madjack, Вы писали:
M>>В принципе верно. Но как теперь в SOAP у которого на входе должна быть строка отдать этот массив байт?
D>В этой теме упоминалась кодировка Base64. Полученный массив байт передаешь в функцию base64encode (или как там она называется) и получаешь строку. На другой стороне делают base64decode и получают массив байт в кодировке UTF-8, из которых создают строку
Спасибо. Именно так и решил эту проблему.
Re[11]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И
Здравствуйте, Madjack, Вы писали:
M>>>В принципе верно. Но как теперь в SOAP у которого на входе должна быть строка отдать этот массив байт?
D>>В этой теме упоминалась кодировка Base64. Полученный массив байт передаешь в функцию base64encode (или как там она называется) и получаешь строку. На другой стороне делают base64decode и получают массив байт в кодировке UTF-8, из которых создают строку
M>Спасибо. Именно так и решил эту проблему.
Ну вот и здорово
Надеюсь ты понял, что у тебя нет (и не было) строк в кодировке 1251
WBR, Igor Evgrafov
Re[7]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
Чего-то я не понял юмора с СОАП клиентом. А почему он не парится на счёт правильной передачи УТФ-8 строк? Это какбэ в ХМЛ документах очень прозрачно поддерживается. Он самописный что ли?
Re: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
От:
Аноним
Дата:
22.06.10 14:53
Оценка:
Наткнулся на эту же проблему.
во многих примерах рекомендуют
message.getBytes("UTF-8") и получается нормальный массив байтов готовый для записи куда угодною Он корректный.
запись проводить любым байтовым выводом
но иногда есть соблазн выводить чуть более удобным способом, через
BufferedWriter(new FileWriter(file))
а тут нужна строка
поэтому ошибочно делаем "неправильную" строку new String(message.getBytes("UTF-8"))
а ее выводим...
BufferedWriter out = new BufferedWriter(new FileWriter(file));
out.write(xml);
забавно, все здорово выводится кроме буквы И, сам от лени наткнулся на проблему.
Но тут никто не гарантирует вывод не правильных пчел с неправильным медом.
Поэтому вывод тока байтам и ему подобными способами без не правильных перекодировок.
Re[9]: Перекодировка Cp1251 -> UTF-8 или заглавная буква "И"
M>Пардон. String text = new String(jtextfield1.getText().getBytes("utf-8")); M>Если использовать String text = jtextfield1.getText(); то возвращается строка в текущей кодировке системы. А мне нужен уже Utf-8.
Тебе же говорили: строка не может быть в какой-то кодировке. Кодировка применима исключительно и только для массива байт. В результате операции "String text = jtextfield1.getText()" у тебя в text будет всегда валидный текст в любой системе, даже если это будет китайский линукс, или парагвайская винда.
Тебе же для передачи на сервер из строки нужно получить представление в виде массива байт в определенной кодировке(в данном случае — утф8).
Новости очень смешные. Зря вы не смотрите. Как будто за наркоманами подсматриваешь. Только тетка с погодой в завязке.
There is no such thing as a winnable war.