Настройка кодировки символов 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());
12.12.2008 05:31:21
Отличные комментарии, ребята - и то, о чем я уже думал сам. К сожалению, есть основной вызов String.getBytes (), который я не могу контролировать. Единственный способ, который я сейчас вижу, - это программная установка кодировки по умолчанию. Любые другие предложения?
Scott T 12.12.2008 05:50:04
может быть, неуместный вопрос, но есть ли разница, когда UTF8 установлен с "UTF8", "UTF-8" или "utf8". Недавно я обнаружил, что контейнеры IBM WAS 6.1 EJB и WEB по-разному обрабатывают (с учетом регистра) строки, используемые для определения кодировки.
igor.beslic 29.05.2011 20:27:34
Просто деталь, но: предпочитаю UTF-8 UTF8 (только первый стандарт). Это все еще применяется в 2012 году ...
Christophe Roussy 22.03.2012 13:16:32
Установка или чтение file.encodingсвойства не поддерживается .
McDowell 24.03.2012 17:26:39
@erickson Мне все еще не ясно с запросом, не правда ли, что file.encoding уместен, когда используются символьные потоки ввода / вывода (все подклассы class Reader& class Writer)? Поскольку class FileInputStreamэто поток ввода-вывода, основанный на байтах, так почему нужно заботиться о наборе символов в потоке ввода-вывода на основе байтов?
overexchange 21.12.2014 04:54:32
16 ОТВЕТОВ
РЕШЕНИЕ

К сожалению, 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()найти текущую кодировку по умолчанию и использовать соответствующий метод или перегрузку конструктора, чтобы указать его.

308
23.05.2017 11:54:46
Для полноты я хотел бы добавить, что с небольшой хитростью вы можете перейти к фактически используемой кодировке по умолчанию (как кешируется), благодаря Гари Кронину: byte [] byteArray = {'a'}; InputStream inputStream = new ByteArrayInputStream (byteArray); InputStreamReader reader = new InputStreamReader (inputStream); String defaultEncoding = reader.getEncoding (); lists.xcf.berkeley.edu/lists/advanced-java/1999-O October/…
Stijn de Witt 11.03.2011 12:11:48
JDK-4163515 содержит дополнительную информацию о настройке file.encodingsysprop после запуска JVM.
Caspar 27.08.2014 04:00:08
Я почесал голову, потому что эта команда не работала на Windows, Linux и Mac отлично ... затем я поместил "вокруг значения, как это: java -D" file.encoding = UTF-8 "-jar
cabaji99 22.09.2017 15:35:46
проверьте мой ответ в случае Java Spring Boot: stackoverflow.com/a/48952844/986160
Michail Michailidis 23.02.2018 17:04:28

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

18
12.12.2008 05:36:04
За исключением, конечно, если вы пишете приложение для настольного компьютера и обрабатываете определенный пользователем текст, который не имеет метаданных кодирования, то кодировка платформы по умолчанию является вашим лучшим предположением относительно того, что пользователь может использовать.
Michael Borgwardt 11.03.2009 15:29:08
@MichaelBorgwardt «тогда кодирование платформы по умолчанию является вашим лучшим предположением», вы, кажется, советуете, что желание изменить значение по умолчанию - не очень хорошая идея. Вы имеете в виду, использовать везде, где это возможно, явное кодирование, используя поставляемое по умолчанию, когда больше ничего не возможно?
Raedwald 10.02.2012 13:33:14
@Redwald: да, это то, что я имел в виду. Кодировка платформы по умолчанию (по крайней мере на компьютере конечного пользователя) обычно используется пользователями в локали, на которую настроена система. Это информация, которую вы должны использовать, если у вас нет более качественной (т.е. специфичной для документа) информации.
Michael Borgwardt 10.02.2012 14:00:19
@MichaelBorgwardt Ерунда. Используйте библиотеку для автоматического определения входной кодировки и сохраните как Unicode с BOM. Это единственный способ справиться и бороться с кодирующим адом.
Aleksandr Dubinsky 16.12.2013 14:24:45
Я думаю, что вы двое не на одной странице. Майкл говорит о декодировании, в то время как Raedwald вы говорите об обработке после декодирования.
WesternGun 21.01.2016 11:37:01

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

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

38
30.03.2017 14:15:10

Непонятно, что вы делаете и не можете контролировать на данный момент. Если вы можете вставить другой класс 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

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

1
16.12.2008 03:59:32
DataInputStream и DataOutputStream являются классами специального назначения, которые никогда не должны использоваться с простыми текстовыми файлами. Используемые ими модифицированные UTF-8 несовместимы с реальными UTF-8. Кроме того, если ОП мог использовать ваше решение, он мог бы также использовать правильный инструмент для этой работы: OutputStreamWriter.
Alan Moore 25.12.2008 04:19:31

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

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

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

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

170
8.03.2009 04:46:37
Знаете ли вы, что утверждение "Подобрано ..." будет напечатано в журналах Tomcat?
thatidiotguy 15.08.2012 13:59:11
Привет, Эдвард Греч. Благодарю за решение. Это было решено моей проблемой в другом сообщении на форуме. stackoverflow.com/questions/14814230/…
Smaug 12.02.2013 05:21:49
UTF8или UTF-8?
Tiny 9.12.2015 13:52:50
@Tiny Java понимает оба. stackoverflow.com/questions/6031877/…
DLight 13.04.2016 12:37:24
Ваше решение сэкономило мое время, большое спасибо!
Sobhan 15.03.2020 21:19:54

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

file.encoding=UTF8
client.encoding.overrideUTF-8
0
19.01.2012 19:23:40
Свойство client.encoding.override представляется специфичным для WebSphere.
Christophe Roussy 20.08.2012 09:29:49

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

    new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))
12
20.01.2012 18:09:42

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

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

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

67
22.03.2013 10:16:57
NoSuchFieldException для меня
SparK 13.03.2013 19:56:47
Для того, чтобы хак сработал, вы должны предположить, что менеджер безопасности отключен. Если у вас нет способа установить флаг JVM, возможно, у вас (возможно) также есть система с включенным менеджером безопасности.
Yonatan 24.08.2013 17:20:17
JDK9 больше не одобряет этот взлом. WARNING: An illegal reflective access operation has occurred • WARNING: Illegal reflective access by [..] • WARNING: Please consider reporting this to the maintainers of [..] • WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations • WARNING: All illegal access operations will be denied in a future release
dotwin 14.01.2018 16:05:42
@Enerccio: Это не очень хороший ответ, это грязный взлом, и проблема, ожидающая своего появления. Это следует использовать только в качестве экстренной меры.
sleske 7.03.2018 18:20:28
@Enerccio: Можно утверждать, должен ли Java «иметь» способ установить это - можно также утверждать, что разработчики «должны» явно указывать кодировку, когда это уместно. Во всяком случае, это решение потенциально может вызвать серьезные проблемы в долгосрочной перспективе, следовательно, предостережение «только для экстренного использования». На самом деле, даже экстренное использование сомнительно, потому что есть поддерживаемый способ сделать это, установив JAVA_TOOL_OPTIONS, как объяснено в другом ответе.
sleske 8.03.2018 13:10:27

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

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

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

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

5
2.07.2019 14:49:14

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

Суть кода:

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

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

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

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

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

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

0
5.10.2017 15:40:32

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

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

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

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

0
14.10.2017 17:14:47

Если вы используете 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"));

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

4
23.02.2018 17:01:53
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)
1
6.03.2018 08:28:28

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

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

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

1
24.04.2018 08:59:03

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

a) Установить переменную окружения (даже в системных настройках 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>
0
3.07.2019 12:58:14