Кодировать строку в UTF-8


190

У меня есть строка с символом «-», и у меня есть некоторые проблемы с ней. Мне нужно закодировать эту строку в кодировку UTF-8. Я попробовал это таким образом, но это не работает:

byte ptext[] = myString.getBytes();
String value = new String(ptext, "UTF-8");

Как мне закодировать эту строку в utf-8?


2
Непонятно, что именно вы пытаетесь сделать. Правильно ли содержит myString символ - и у вас есть проблемы с преобразованием его в байтовый массив (в этом случае см. Ответы Питера и Амира), или myString поврежден, и вы пытаетесь это исправить (в этом случае см. Ответы от Joachim и я)?
Майкл Боргвардт

Мне нужно отправить myString на сервер с кодировкой utf-8, и мне нужно преобразовать символ «ñ» в кодировку utf-8.
Алекс

1
Хорошо, если этот сервер ожидает UTF-8, то вам нужно отправить его байтами, а не строкой. Итак, согласно ответу Петра, укажите кодировку в первой строке и опустите вторую строку.
Майкл Боргвардт

@ Майкл: Я согласен, что не ясно, каково реальное намерение здесь. Похоже, что возникает много вопросов, когда люди пытаются явно преобразовать строки и байты, а не разрешают {In,Out}putStream{Read,Writ}ersделать это за них. Интересно, почему?
tchrist

1
@ Майкл: Спасибо, я полагаю, это имеет смысл. Но это также делает его сложнее, чем нужно, не так ли? Я не очень люблю языки, которые работают таким образом, и поэтому стараюсь избегать работы с ними. Я думаю, что модель Java строк символов вместо байтов делает вещи намного проще. Perl и Python также разделяют модель «все - строки Юникода». Да, во всех трех вы все еще можете получить байты, если вы работаете над этим, но на практике это кажется редким, что вам действительно нужно: это довольно низкий уровень. К тому же, это похоже на то, что я чищу кошку в неправильном направлении, если ты понимаешь, о чем я. :)
tchrist

Ответы:


140

String объекты в Java используют кодировку UTF-16, которую нельзя изменить.

Единственное, что может иметь другую кодировку - это byte[]. Так что если вам нужны данные UTF-8, то вам нужен byte[]. Если у вас есть Stringнепредвиденные данные, то проблема в более раннем месте, которое неправильно преобразовало некоторые двоичные данные в String(то есть использовалось неправильное кодирование).


92
Технически говоря, byte [] не имеет никакой кодировки. Тем не менее, байтовый массив PLUS может дать вам строку.
Петр Штибраны

1
@ Питер: правда. Но присоединение кодировки к нему имеет смысл только для byte[], это не имеет смысла String(если только кодировка не является UTF-16, в этом случае это имеет смысл, но это все еще ненужная информация).
Иоахим Зауэр

4
String objects in Java use the UTF-16 encoding that can't be modified. У вас есть официальный источник этой цитаты?
Ахмад Хаджар

@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… «Платформа Java использует представление UTF-16 в массивах символов и в классах String и StringBuffer».
Макси Гис

173

Как насчет использования

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)

Смотрите мое обсуждение с Питером. Но если его предположение относительно вопроса верное, ваше решение все равно не будет идеальным, поскольку оно возвращает ByteBuffer.
Майкл Боргвардт

8
Но как мне получить закодированную строку? он возвращает ByteBuffer
Алекс

7
@Alex: невозможно иметь строку Java в кодировке UTF-8. Вам нужны байты, поэтому либо используйте ByteBuffer напрямую (может быть даже лучшим решением, если ваша цель - отправить его через сетевую коллекцию), либо вызовите array () для него, чтобы получить байт []
Майкл Боргвардт,

2
Что-то еще, что может быть полезным, это использовать перечисление Charsets.UTF_8 в Guava вместо String, которое может генерировать исключение UnsupportedEncodingException. String -> байты: myString.getBytes(Charsets.UTF_8)и байты -> String new String(myByteArray, Charsets.UTF_8).
смеется_март

24
Еще лучше, используйте StandardCharsets.UTF_8. Доступно в Java 1.7+.
Kat

81

В Java7 вы можете использовать:

import static java.nio.charset.StandardCharsets.*;

byte[] ptext = myString.getBytes(ISO_8859_1); 
String value = new String(ptext, UTF_8); 

Это имеет преимущество перед тем, getBytes(String)что не объявляет throws UnsupportedEncodingException.

Если вы используете более старую версию Java, вы можете объявить константы charset самостоятельно:

import java.nio.charset.Charset;

public class StandardCharsets {
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    //....
}

2
Это правильный ответ. Если кто-то хочет использовать строковый тип данных, он может использовать его в нужном формате. Остальные ответы указывают на тип в байтах.
Neeraj Shukla

Работает в 6. Спасибо.
Ицик Моихас

Правильный ответ для меня тоже. Одна вещь, хотя, когда я использовал как выше, немецкий символ изменился на? Итак, я использовал это: byte [] ptext = myString.getBytes (UTF_8); Строковое значение = новая строка (ptext, UTF_8); Это работало нормально.
Фархан Хафиз,

3
Пример кода не имеет смысла. Если вы сначала конвертируете в ISO-8859-1, то этот массив байтов не является UTF-8, поэтому следующая строка совершенно неверна. Он будет работать для ASCII строк, конечно, но вы можете также сделать простую копию: String value = new String(myString);.
Алексис Вилке

76

Используйте byte[] ptext = String.getBytes("UTF-8");вместо getBytes(). getBytes()использует так называемую «кодировку по умолчанию», которая может не соответствовать UTF-8.


9
@Michael: у него явно проблемы с получением байтов из строки. Как getBytes (кодировка) упускает смысл? Я думаю, что вторая строка просто чтобы проверить, сможет ли он преобразовать ее обратно.
Питер Штибраны

1
Я интерпретирую это как наличие поврежденной строки и пытаюсь «исправить» ее путем преобразования в байты и обратно (распространенное недоразумение). Нет фактического указания на то, что вторая строка просто проверяет результат.
Майкл Боргвардт

@ Майкл, нет, нет, это просто моя интерпретация. Твой просто другой.
Питер Штибраны

1
@ Питер: ты прав, нам нужно уточнить у Алекса, что он на самом деле имеет в виду. Не могу отменить понижение, хотя, если ответ не редактируется ...
Майкл Боргвардт

33

Строка Java всегда внутренне кодируется в UTF-16 - но вы действительно должны думать об этом так: кодирование - это способ перевода между строками и байтами.

Так что, если у вас есть проблема с кодировкой, к тому времени, когда у вас есть String, уже слишком поздно ее исправлять. Вам нужно исправить место, где вы создаете эту строку из файла, БД или сетевого подключения.


1
Распространенной ошибкой считается, что строки внутренне кодируются как UTF-16. Обычно это так, но если это только специфическая для реализации деталь класса String. Поскольку внутреннее хранилище символьных данных недоступно через открытый API, конкретная реализация String может решить использовать любую другую кодировку.
jarnbjo

4
@jarnbjo: API явно заявляет: «Строка представляет строку в формате UTF-16». Использование чего-либо еще в качестве внутреннего формата было бы крайне неэффективно, и все известные мне реализации действительно используют UTF-16 для внутреннего использования. Поэтому, если вы не можете сослаться на тот, который этого не делает, вы занимаетесь довольно абсурдной укладкой волос.
Майкл Боргвардт

Абсурдно ли проводить различие между публичным доступом и внутренним представлением структур данных?
jarnbjo

6
JVM (насколько это вообще относится к виртуальной машине) использует UTF-8 для строкового кодирования, например, в файлах классов. Реализация java.lang.String отделена от JVM, и я мог бы легко реализовать класс для вас, используя любую другую кодировку для внутреннего представления, если вам действительно необходимо понять, что ваш ответ неверен. Использование UTF-16 в качестве внутреннего формата в большинстве случаев также крайне неэффективно, когда речь идет о потреблении памяти, и я не понимаю, почему, например, реализации Java для встроенного оборудования не оптимизируют память, а не производительность.
jarnbjo

1
@jarnbjo: И еще раз: до тех пор , как вы не можете дать пример бетона в виртуальной машине Java, стандартный API реализация делает внутренне использовать что - то другое , чем UTF-16 для выполнения строк, мое утверждение верно. И нет, класс String на самом деле не отделен от JVM из-за таких вещей, как intern () и пул констант.
Майкл Боргвардт

22

Вы можете попробовать это так.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 

1
Я сходил с ума. Спасибо, что байты в "ISO-8859-1" первыми стали решением проблемы.
Джан Гомен

2
Это не верно. Если ваша строка содержит символы Unicode, преобразование ее в 8859-1 вызовет исключение или, что еще хуже, даст вам недопустимую строку (возможно, строку без этих символов с кодовой точкой 0x100 и более).
Алексис Уилк

12

Через мгновение я прошел эту проблему и сумел решить ее следующим образом

сначала мне нужно импортировать

import java.nio.charset.Charset;

Затем я должен был объявить константу для использования UTF-8иISO-8859-1

private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final Charset ISO = Charset.forName("ISO-8859-1");

Тогда я мог бы использовать это следующим образом:

String textwithaccent="Thís ís a text with accent";
String textwithletter="Ñandú";

text1 = new String(textwithaccent.getBytes(ISO), UTF_8);
text2 = new String(textwithletter.getBytes(ISO),UTF_8);

1
идеальное решение.
Tunde Pizzle

9
String value = new String(myString.getBytes("UTF-8"));

и, если вы хотите читать из текстового файла с кодировкой «ISO-8859-1»:

String line;
String f = "C:\\MyPath\\MyFile.txt";
try {
    BufferedReader br = Files.newBufferedReader(Paths.get(f), Charset.forName("ISO-8859-1"));
    while ((line = br.readLine()) != null) {
        System.out.println(new String(line.getBytes("UTF-8")));
    }
} catch (IOException ex) {
    //...
}

2

Я использовал код ниже, чтобы закодировать специальный символ, указав формат кодирования.

String text = "This is an example é";
byte[] byteText = text.getBytes(Charset.forName("UTF-8"));
//To get original string from byte.
String originalString= new String(byteText , "UTF-8");

2

Краткое пошаговое руководство по настройке кодировки по умолчанию для NetBeans UTF-8. В результате NetBeans создаст все новые файлы в кодировке UTF-8.

Пошаговое руководство по кодировке UTF-8 по умолчанию в NetBeans

  • Перейдите в папку etc в каталоге установки NetBeans.

  • Отредактируйте файл netbeans.conf

  • Найти строку netbeans_default_options

  • Добавьте -J-Dfile.encoding = UTF-8 внутри кавычек внутри этой строки

    (пример: netbeans_default_options="-J-Dfile.encoding=UTF-8")

  • Перезапустите NetBeans

Вы устанавливаете кодировку по умолчанию NetBeans UTF-8.

Ваши netbeans_default_options могут содержать дополнительные параметры внутри кавычек. В таком случае добавьте -J-Dfile.encoding = UTF-8 в конце строки. Отделите его пробелом от других параметров.

Пример:

netbeans_default_options = "- J-клиент -J-Xss128m -J-Xms256m -J-XX: PermSize = 32m -J-Dapple.laf.useScreenMenuBar = true -J-Dapple.awt.graphics.UseQuartz = true -J-Dsun. java2d.noddraw = true -J-Dsun.java2d.dpiaware = true -J-Dsun.zip.disableMemoryMapping = true -J-Dfile.encoding = UTF-8 "

вот ссылка для получения дополнительной информации


0

Это решило мою проблему

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.