Кодиране на знаци в Java, конвертиране на ISO в UTF

Тази тема е била обект на много дискусии и въпреки това все още виждаме да се появяват нови. Моят сценарий е следният:

Рамка на Java, работеща на Linux сървър, където UTF-8 е стандартното кодиране на знаци в JVM. Рамката се състои от някои услуги, получаващи Tibco RV съобщения, които трябва да бъдат обработени. Някои от тези съобщения съдържат различни от ASCII знаци и се изпращат от Windows сървър, а ISO8859-1 е кодирането, използвано при създаването на съобщението. Сега, когато данните се извличат от съобщението Tib rv, проблемните полета „пристигат“ като Java обекти и трябва да бъдат прехвърлени към низове... И тук все още не съм успял да извлека ISO8859-1 низове, съдържащи не ASCII символи (шведски "","","") към UTF-8 низ по правилен начин. Опитах да използвам следните методи:

String isoStreet = new String(response.get("street").toString().getBytes(StandardCharsets.ISO_8859_1),java.nio.charset.StandardCharsets.UTF_8);

и аз също се опитах да използвам енкодерите/декодерите в пакета java.nio без успех.

Това, което също е интересно е, че използвам PuttY, за да се свържа със сървър, където услугите се хостват и работят. И оттам имам възможността да направя директна заявка за Tibco rv от обвивката (използвайки клиента tibcorvsend) и изглежда, че трябва да задам отдалечения набор от знаци на ISO8859-1 в PuttY (Window_>Translation), преди да вляза в сървър и направете тази Tib rv заявка - когато това бъде направено, тези не-ASCII символи се показват правилно в отговора, без значение какво кодиране задам в отдалечения Linux сървър. Използването на „export LC_ALL=en_US.UTF-8“ или „export LC_ALL=sv_SE.iso88591“ няма значение в този случай... само какво отдалечено кодиране съм задал в PuttY...

Това трябва да означава, че съобщението за отговор изглежда добре и поне черупката може да изведе правилни знаци. Но когато съм вътре в Java VM (използвайки услуги на Java), предполагам, че полетата за отговор се натискат тихо в низове при отстраняване на грешки и преглеждане на отговорния обект (не искам това преобразуване в низове) в изгледа за гледане... не съм сигурен дали можете да ме последвате в това , ако не, може да се опитам да бъда по-ясен, ако е необходимо...

Всеки принос по този проблем, всеки

Поздрави /Р


person R E    schedule 12.02.2015    source източник


Отговори (1)


кодиране на знаци указва как текстът, който се състои от знаци, се превежда в байтове и обратно. Както знаете, има различни кодировки на знаци, като ASCII, ISO-8859-1 и UTF-8.

Низът се състои от знаци. В един момент искате да конвертирате тези символи в байтове, така че да можете да ги изпратите по мрежа, да ги съхраните във файл или каквото искате да направите. Използвате кодиране на знаци, за да преведете низа в байтове. И от другата страна, където получавате байтовете, използвате същото кодиране на знаци, за да преведете байтовете обратно в знаци в низ.

Нека да видим защо ред като този, който публикувахте, е неправилен. Нека първо го пренапишем, за да мога да обясня частите:

String street = response.get("street").toString();
byte[] streetBytes = street.getBytes(StandardCharsets.ISO_8859_1);
String isoStreet = new String(streetBytes, StandardCharsets.UTF_8);

В първия ред получавате някои данни от отговора и ги конвертирате в низ. (Какво връща response.get("street")?).

Във втория ред кодирате този низ, като използвате набора от символи ISO-8859-1. Получавате масив от байтове, който съдържа валидни кодове на знаци ISO-8859-1 за знаците в низа.

В третия ред преобразувате байтовете в низ и се преструвате, че байтовете са UTF-8 байтове. Това очевидно е грешно, защото байтовете са данни ISO-8859-1, а не UTF-8 данни. Когато направите това, може да получите грешни знаци или дори изключение, ако масивът от байтове съдържа поредица от байтове, която не е валиден знак според UTF-8.

Едно нещо, което трябва да знаете е, че низът се състои само от символи. Низът сам по себе си няма кодиране. Използвате кодиране на знаци, за да преведете низ в байтове и обратно. Не можете да "промените кодирането на знаци на низ", защото кодирането на знаци просто не е свойство на низа. Точно както числото не е вътрешно десетично или шестнадесетично - това са просто различни начини за представяне на едно и също число.

Това, което трябва да направите е:

  • В момента, в който пишете съобщението, уверете се, че използвате правилното кодиране на знаци за преобразуване на низове в байтове.

  • В момента, в който четете съобщението, уверете се, че използвате правилното кодиране на знаци за преобразуване на байтове в низове.

Не четете нещо в низ, като използвате стандартното кодиране на знаци на платформата и след това се опитвайте да „преобразувате низа“. Това не работи.

person Jesper    schedule 12.02.2015
comment
Благодаря за отговора... Един проблем е, че нямам никакво влияние върху това как се създава отговорът, който получаваме. Това е външна система, LDAP сървър, работещ на windows сървър. response.get(fieldName) ще върне обект (или null, ако полето не присъства в съобщението за отговор на Tibco) Но всъщност това е поле String - всички полета в съобщение на Tibco RV се изпращат като обекти, но обектите са по-скоро контейнери на Низове, цели числа и подобни. И все пак не знам как да накарам тези знаци от съобщението за отговор в Java String (или байт []) - person R E; 12.02.2015
comment
Хм, не съм сигурен дали това е правилният начин да отговоря на вашия отговор... може би трябваше вместо това да публикувам отговор??? - person R E; 12.02.2015
comment
Ще трябва да анализирате кода си и да разберете какво точно е поставено в съобщението и какво точно получавате от него. Надявам се отговорът ми да ви помогне да разберете кодирането на знаци, така че да можете да разрешите това ефективно. - person Jesper; 13.02.2015