Комментарии 53
А то можно было бы сделать заголовок ещё лучше: «Java снова не тормозит» (если кто помнит про события 11-летной давности: «Робот под управлением Linux с софтом на Java убился об стену»).
А тем временем в Microsoft портировали проблему с кодировками из Java в powershell :)
Рекомендуемый всюду способ считывания xml-файлов:
[xml]$xml = Get-Content Путь:\к\файлу.xml
При этом сначала считывается файл в системной кодировке, а потом превращается в DOM. А на то, что в самом файле может быть указана другая кодировка — не важно...
Вместе с тем, для Get-Content можно указать кодировку параметром -Encoding и не иметь проблем.
Это если кодировка файла — известна. А если нет?
Тот же XmlDocument
, лежащий за синонимом [xml]
, умеет читать любой поток байт, определяя кодировку из декларации. Так же как XmlReader
и XDocument
.
Но в powershell эту возможность так просто использовать не получится — вот и гуляет ошибочное решение по интернету…
Это ж уже велосипед будет… Правильный способ — такой:
$xml = New-Object ([xml])
$xml.Load((Get-Item путь\к\файлу.xml))
Если путь абсолютный — то Get-Item не нужен
Проблема исключительно в том, что в инете советуют способ через Get-Content
wcout << L"test" << endl; //будет выведено
wcout << L"тест" << endl; //не будет выведено
wcout << L"test" << endl; //НЕ будет выведено
Приходится делать заглушки с WriteConsoleW
Чтобы поработать с этим текстом в Java нам нужно загнать данные в String. Как это сделать?
Или еще вот так можно:
String str = new String(Files.readAllBytes(Paths.get("file")), StandardCharsets.UTF_8);
Там же все написано русским по белому! Java стоит не на аппарате, а в центре управления. Пруф конечно же все еще нужен — но ваше возражение совсем не по делу.
При чем здесь Java, которая изначально задумывалась для полной поддержки Юникода, непонятно, ведь для Windows родная кодировка — UTF-16LE, начиная где-то с Windows 95, за 3 года до выхода 1-й Java.
У меня например консоль cmd.exe выдает:
H:\>chcp
Active code page: 437
Выводить кириллический текст в нее даже в UTF-8 бесполезно. При этом поставить правильную кодировку еще полдела, надо еще и шрифт поменять на TrueType.
Java оперирует внутри себя 16-битными Unicode сodepoint, но внешний мир жесток и несовершенен (особенно в Windows), поэтому статья правильно акцентирует внимание на том, что про кодировку помнить нужно и проставлять лучше явно. С другой стороны, на правильных операционных системах дефолтная кодировка в 99% работает корректно.
Так о том и речь, что надо бы им @Deprecated поставить.
Хотя бы сменили бы желтушный заголовок, раз это лишь предположение. Мы ведь не «горячие новости» из smi2 тут читаем, а вполне адекватные посты.
Укажите примерно так:
> Откуда в Java всплывают проблемы с кодировками и возможная причина падения марсианского зонда
Ещё крайне полезно использовать forbidden-apis checker, умеет ловить следующее:
jdk-unsafe-*
— использование методов jdk, которые неявно используют charset, locale или timezone по умолчанию;jdk-deprecated-*
— использование deprecated методов и jdk;jdk-internal-*
— использование внутренних методов jdk из пакетов, выдаваемых Security.getProperty("package.access");jdk-non-portable
— множество потенциально несовместимых api, включающееjdk-internal
;jdk-system-out
— думаю и так ясно;jdk-reflection
— куски использования reflection, которые должны поломаться в java 9;commons-io-unsafe-*
— использование методов с default charset.
- com.oracle.webservices.internal.
- com.oracle.xmlns.internal.
- com.sun.activation.registries.
- com.sun.corba.se.
- com.sun.imageio.
- com.sun.istack.internal.
- com.sun.jmx.
- com.sun.media.sound.
- com.sun.naming.internal.
- com.sun.org.apache.bcel.internal.
- com.sun.org.apache.regexp.internal.
- com.sun.org.apache.xalan.internal.extensions.
- com.sun.org.apache.xalan.internal.lib.
- com.sun.org.apache.xalan.internal.res.
- com.sun.org.apache.xalan.internal.templates.
- com.sun.org.apache.xalan.internal.utils.
- com.sun.org.apache.xalan.internal.xslt.
- com.sun.org.apache.xalan.internal.xsltc.cmdline.
- com.sun.org.apache.xalan.internal.xsltc.compiler.
- com.sun.org.apache.xalan.internal.xsltc.trax.
- com.sun.org.apache.xalan.internal.xsltc.util.
- com.sun.org.apache.xerces.internal.
- com.sun.org.apache.xml.internal.res.
- com.sun.org.apache.xml.internal.security.
- com.sun.org.apache.xml.internal.serializer.utils.
- com.sun.org.apache.xml.internal.utils.
- com.sun.org.apache.xpath.internal.
- com.sun.org.glassfish.
- com.sun.proxy.
- com.sun.xml.internal.
- jdk.internal.
- jdk.nashorn.internal.
- jdk.nashorn.tools.
- oracle.jrockit.jfr.
- org.jcp.xml.dsig.internal.
- sun.
Естественно, можно добавлять свои сигнатуры.
Когда в винде появился юникод?
Видимо, это связано с тем, что в мир Java иммигрировали люди, не привыкшие решать проблему кодировок. Скажем, в C# по умолчанию применяется кодировка UTF-8, поэтому разработчик, переехавший с C#, вполне разумно считает, что InputStreamReader по умолчанию использует эту же кодировку, и не вдается в детали его реализации.
Java и C#, нужно смотреть контракт класса, который используешь.
В C# действительно при чтении файлов по умолчанию используется UTF8, или определяется по заголовку (для XML) или BOM, если заголовок не определен или отсутствует BOM.
Тем не менее, и тут есть вероятность ошибки автоматического определения кодировки.
А что, если BOM это BOM, а полезные данные? — при создании объекта-кодировки можно указать, использовать ли BOM, когда эта кодировка передается ридеру (и тут тоже есть свои умолчания — использовать BOM).
Поэтому программист тут тоже должен понимать, что именно делает, и принимать решение, что делать.
И в C# хватает своих неоднозначностей — например, использование глобальных настроек CurrentCulture при работе со строками.
А в библиотеке Guava, в аналогичном классе Files, вообще нет методов, имеющих кодировку по умолчанию (например, Files.toString()).
Если все начнут хардкодить кодировки, получится еще больший ацкий зоопарк, на который даже параметрами командной строки не повлиять. Просто кодировка по умолчанию должна быть не системная, а на всех платформах всегда и везде — UTF-8. Кому хочется легаси и экзотики — пускай передают параметры или хардкодят через предложенные методы, но в этом случае при каждом запуске приложения и каждом чтении файла должен выскакивать назойливый диалог: «вы используете устаревшую кодировку, настоятельно рекомендуем конвертировать ваши файлы в UTF-8».
1. окей гугл, исходники openjdk без регистрации.
2. окей, написать обертку для бинарники java, подставляющую нужные аргументы — не вариант?
3. если «не вариант» — тем же easyhook/LD_PRELOAD/%решениенейм% быстро запилить фильтр для запускающихся процессов с целью передачи нужных аргументов. Тем более что для Java на современных машинах под виндой приходится примерно таким образом «портить» обращение к функциям, возвращающим информацию о DPI дисплея ради некоторых древних приложений типа Packet Tracer.
When merged into the navigation system, the erroneous information generated an estimated altitude that was negative – that is, below ground level. This in turn successively triggered a premature release of the parachute and the backshell, a brief firing of the braking thrusters and finally activation of the on-ground systems as if Schiaparelli had already landed. In reality, the vehicle was still at an altitude of around 3.7 km.
Короче какой-то сенсор послал максимальное значение в компьютер и тот решил включить тормоза и отстрелить парашют.
Откуда в Java всплывают проблемы с кодировками и возможная причина падения марсианского зонда