Установка кодировки символов Java по умолчанию?

Как правильно установить кодировку символов по умолчанию, используемую JVM (1.5.x) программно?

Я прочитал это -Dfile.encoding=whatever Раньше был путь к старым JVM... У меня нет такой роскоши по причинам, в которые я не пойду.

Я пытался:

System.setProperty("file.encoding", "UTF-8");

И свойство устанавливается, но, похоже, не вызывает последний вызов getBytes ниже для использования UTF8:

    System.setProperty("file.encoding", "UTF-8");

    byte inbytes[] = new byte[1024];

    FileInputStream fis = new FileInputStream("response.txt");
    fis.read(inbytes);
    FileOutputStream fos = new FileOutputStream("response-2.txt");
    String in = new String(inbytes, "UTF8");
    fos.write(in.getBytes());

19 ответов

Решение

К сожалению, file.encoding свойство должно быть указано при запуске JVM; ко времени ввода вашего основного метода кодировка символов, используемая String.getBytes() и конструкторы по умолчанию InputStreamReader а также OutputStreamWriter был постоянно кэширован.

Как указывает Эдвард Греч, в особом случае, подобном этому, переменная окружения JAVA_TOOL_OPTIONS может использоваться для указания этого свойства, но обычно это делается так:

java -Dfile.encoding=UTF-8 … com.x.Main

Charset.defaultCharset() будет отражать изменения в file.encoding свойство, но большая часть кода в основных библиотеках Java, которые должны определять кодировку символов по умолчанию, не использует этот механизм.

Когда вы кодируете или декодируете, вы можете запросить file.encoding собственность или Charset.defaultCharset() найти текущую кодировку по умолчанию и использовать соответствующую перегрузку метода или конструктора, чтобы указать ее.

Из документации по интерфейсу инструмента JVM™

Поскольку к командной строке не всегда можно получить доступ или изменить ее, например, во встроенных виртуальных машинах или просто виртуальных машинах, запущенных глубоко внутри сценариев, JAVA_TOOL_OPTIONS предоставляется переменная, чтобы в этих случаях могли запускаться агенты.

Установив переменную среды (Windows) JAVA_TOOL_OPTIONS в -Dfile.encoding=UTF8, (Java) System свойство будет установлено автоматически при каждом запуске JVM. Вы будете знать, что параметр был выбран, потому что следующее сообщение будет опубликовано System.err:

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

У меня есть хакерский способ, который определенно работает!!

System.setProperty("file.encoding","UTF-8");
Field charset = Charset.class.getDeclaredField("defaultCharset");
charset.setAccessible(true);
charset.set(null,null);

Таким образом, вы собираетесь обмануть JVM, который подумает, что charset не установлен, и заставит его снова установить его в UTF-8 во время выполнения!

Я думаю, что лучший подход, чем установка набора символов по умолчанию для платформы, особенно если учесть, что у вас есть ограничения по влиянию на развертывание приложения, не говоря уже о платформе, - это вызвать гораздо более безопасный String.getBytes("charsetName"), Таким образом, ваше приложение не зависит от не зависящих от него вещей.

Я лично чувствую, что String.getBytes() не рекомендуется, так как это вызвало серьезные проблемы в ряде случаев, которые я видел, когда разработчик не учел возможное изменение кодировки по умолчанию.

Я не могу ответить на ваш первоначальный вопрос, но я хотел бы дать вам несколько советов - не зависите от кодировки JVM по умолчанию. Всегда лучше явно указать желаемую кодировку (то есть "UTF-8") в вашем коде. Таким образом, вы знаете, что он будет работать даже в разных системах и конфигурациях JVM.

Попробуй это:

    new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))

Если вы используете Spring Boot и хотите передать аргумент file.encoding в JVM вы должны запустить его так:

mvn spring-boot:run -Drun.jvmArguments="-Dfile.encoding=UTF-8"

это было необходимо для нас, так как мы использовали JTwig шаблоны и операционная система имели ANSI_X3.4-1968 что мы узнали через System.out.println(System.getProperty("file.encoding"));

Надеюсь, это поможет кому-то!

Я много чего перепробовал, но пример кода здесь отлично работает. Ссылка на сайт

Суть кода:

String s = "एक गाव में एक किसान";
String out = new String(s.getBytes("UTF-8"), "ISO-8859-1");

У нас были те же проблемы. Мы методично попробовали несколько предложений из этой статьи (и других) безрезультатно. Мы также попытались добавить -Dfile.encoding=UTF8, но ничего не получалось.

Для людей, которые имеют эту проблему, следующая статья, наконец, помогла нам отследить, описывает, как настройка локали может сломать Unicode/UTF-8 в Java / Tomcat

http://www.jvmhost.com/articles/locale-breaks-unicode-utf-8-java-tomcat

Правильная настройка локали в файле ~/.bashrc сработала у нас.

Моя команда столкнулась с той же проблемой на машинах с Windows... затем мне удалось решить ее двумя способами:

а) Установить переменную среды (даже в системных настройках Windows)

JAVA_TOOL_OPTIONS
-Dfile.encoding = UTF8

б) Добавьте следующий фрагмент в свой pom.xml:

 -Dfile.encoding=UTF-8 

В

 <jvmArguments>
 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
 -Dfile.encoding=UTF-8
 </jvmArguments>

Решите эту проблему в моем проекте. Надеюсь, это кому-то поможет.

Я использую java-фреймворк LIBGDX, и у меня была эта проблема в моем проекте студии Android. В Mac OS кодировка правильная, но в Windows 10 специальные символы и символы, а также русские символы отображаются в виде вопросов типа:????? и другие неправильные символы.

  1. Изменение настроек проекта студии Android:File->Settings...->Editor-> File Encodings в UTF-8 во всех трех полях (глобальная кодировка, кодировка проекта и значение по умолчанию ниже).

  2. В любом наборе файлов java:

    System.setProperty("file.encoding","UTF-8");

  3. И для журнала отладки тестовой печати:

    System.out.println("My project encoding is : "+ Charset.defaultCharset());

Я использую Amazon (AWS) Elastic Beanstalk и успешно изменил его на UTF-8.

В Elastic Beanstalk выберите Конфигурация> Программное обеспечение, "Свойства среды". Добавьте (имя) JAVA_TOOL_OPTIONS с (значение) -Dfile.encoding=UTF8

После сохранения среда перезапустится с кодировкой UTF-8.

Непонятно, чем вы занимаетесь, и не можете контролировать этот момент. Если вы можете вставить другой класс OutputStream в целевой файл, вы можете использовать подтип OutputStream, который преобразует Strings в байты под определенным вами набором символов, скажем, UTF-8 по умолчанию. Если модифицированный UTF-8 достаточно для ваших нужд, вы можете использовать DataOutputStream.writeUTF(String):

byte inbytes[] = new byte[1024];
FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
String in = new String(inbytes, "UTF8");
DataOutputStream out = new DataOutputStream(new FileOutputStream("response-2.txt"));
out.writeUTF(in); // no getBytes() here

Если такой подход неосуществим, может помочь, если вы уточнить здесь, что именно вы можете и не можете контролировать с точки зрения потока данных и среды выполнения (хотя я знаю, что иногда это легче сказать, чем определить). Удачи.

Настройка аргументов jvm при запуске приложения помогла мне решить эту проблему. java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8.

file.encoding=UTF-8 - Это помогает иметь в файле символы Юникода.

sun.jnu.encoding=UTF-8 - Это помогает использовать символы Unicode в качестве имени файла в файловой системе.

mvn clean install -Dfile.encoding=UTF-8 -Dmaven.repo.local=/path-to-m2

Команда работала с exec-maven-plugin для устранения следующей ошибки при настройке задачи jenkins.

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512m; support was removed in 8.0
Error occurred during initialization of VM
java.nio.charset.IllegalCharsetNameException: "UTF-8"
    at java.nio.charset.Charset.checkName(Charset.java:315)
    at java.nio.charset.Charset.lookup2(Charset.java:484)
    at java.nio.charset.Charset.lookup(Charset.java:464)
    at java.nio.charset.Charset.defaultCharset(Charset.java:609)
    at sun.nio.cs.StreamEncoder.forOutputStreamWriter(StreamEncoder.java:56)
    at java.io.OutputStreamWriter.<init>(OutputStreamWriter.java:111)
    at java.io.PrintStream.<init>(PrintStream.java:104)
    at java.io.PrintStream.<init>(PrintStream.java:151)
    at java.lang.System.newPrintStream(System.java:1148)
    at java.lang.System.initializeSystemClass(System.java:1192)

Недавно я наткнулся на систему Notes 6.5 местной компании и обнаружил, что в веб-почте будут отображаться неопознаваемые символы при установке Windows, не относящейся к Zhongwen. Покопался несколько недель в Интернете, разобрался всего несколько минут назад:

В свойствах Java добавьте следующую строку в Параметры времени выполнения

-Dfile.encoding=MS950 -Duser.language=zh -Duser.country=TW -Dsun.jnu.encoding=MS950

Настройка UTF-8 не будет работать в этом случае.

После комментария @Caspar к принятому ответу предпочтительный способ исправить это в соответствии с Sun:

msgstr "изменить локаль базовой платформы перед запуском вашей Java-программы."

http://bugs.java.com/view_bug.do?bug_id=4163515

Для докера см.:

http://jaredmarkell.com/docker-and-locales/

Мы устанавливаем два системных свойства вместе, и это заставляет систему принимать все в utf8

file.encoding=UTF8
client.encoding.override=UTF-8

Если вы используете AZURE, используйте следующий параметр в файле webapp-component.yml.

      systemProperties:
   file.encoding: "UTF8"
   client.encoding.override: "UTF-8"

Примечание. Если вы столкнулись с проблемой кодирования, когда ваш запрос заменяется на «?» это ваше решение.

Другие вопросы по тегам