Как прочитать «Разделитель списка» из ОС в Java? - PullRequest
8 голосов
/ 08 мая 2009

Я пишу CSV-экспортер на Java, который должен учитывать пользовательские настройки пользователя, особенно «разделитель списков» для использования в качестве разделителя.

В Windows этот разделитель списка можно установить в

Control Panel -> Regional and Language Options -> Regional Options -> Customize

Я не знаю о других операционных системах, но я почти уверен, что вы можете изменить это и в других ОС.

Каков наилучший способ получить эту пользовательскую настройку из ОС в Java? Я нахожусь в среде Eclipse RCP, поэтому я могу использовать решения, связанные с RCP, если есть что-то доступное.

Ответы [ 7 ]

6 голосов
/ 08 мая 2009

Из комментариев этот ответ :

Чтение настроек, специфичных для ОС, необходимо, чтобы у меня было .

Так что, если ОС, отличные от Windows , не имеют такой настройки?

Я предлагаю вам прочитать его из реестра в Windows (как указано здесь ): Чтение / запись в реестр Windows с использованием Java . На других платформах просто используйте хорошее значение по умолчанию и, возможно, по крайней мере в Unix, также поддержите его настройку с помощью пользовательской переменной среды (которую вы хорошо документируете): Как мой java-код может читать переменные среды ОС? .

Мое внутреннее чувство, что операционные системы повсеместно не имеют (общесистемного или пользовательского) параметра «Разделитель списков», конечно, может быть неправильным, но я сомневаюсь в этом.

6 голосов
/ 08 мая 2009

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

5 голосов
/ 29 ноября 2010

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

Я посмотрел на некоторые локали в Windows и увидел, что разделителем списка является либо ";" или же ",". Я слышал, что в каком-то непонятном месте есть еще один персонаж, но сам этого не видел. Так что, если вы можете сделать свой код для обработки обоих ";" и "," как разделители списка, тогда вы, вероятно, охватите большинство случаев.

Кроме того, похоже, что когда "," используется в качестве десятичного разделителя, тогда "," никогда не используется в качестве разделителя списка. Я предполагаю, что в противном случае числа будут невозможно различить в списке: 1,2,3,4 может быть 1,2, 3,4 или 1, 2,3. В этих случаях ";" используется в качестве разделителя списка. К сожалению, обратное неверно. Арабский имеет "." как десятичный символ и ";" в качестве разделителя списка.

Так что я думаю, что правило, которому можно разумно безопасно следовать:

if (decimalSeparator == ',') 
    then listSeparator = ';'
else if (decimalSeparator == '.') 
    then listSeparator = new char[] {';', ','}
2 голосов
/ 08 мая 2009

Из любопытства я немного искал тему, и, похоже, у Java нет такого понятия из коробки.

Демо Locales дает довольно полный список настроек локали, и там нет разделителя списка.

Я видел вопрос форума , относящийся к пакету sun.text.resources, который является закрытым и не рекомендуется. Вы не найдете много других ссылок на этот пакет, похоже, что он находится в jre / lib / ext / localedata.jar, хотя моя последняя копия содержит в основном азиатские локали.

Приведенные выше советы являются правильными, или вы можете исследовать и использовать личный список для каждой локали. Возможно, я бы посмотрел на библиотеку IBM ICU (я думаю, на языке C), которая, кажется, имеет довольно большой список настроек локали. Согласно замечанию , ICU сама получает информацию из стандарта ISO, который следует исследовать в качестве основного поставщика информации.

1 голос
/ 20 ноября 2018

Ну, я вижу это как серьезную тему!

Дело в том, что в Windows есть Excel. И многие программы должны взаимодействовать с ним. Excel использует локаль разделителя списка (разделение ячеек).

Основная проблема заключается в том, что «Значения, разделенные запятыми» не работают за пределами США (испанский (США)) и английского, потому что вы не можете использовать тот же символ разделителя списка, что и десятичный разделитель. Таким образом, мир за пределами США и Англии (включая армию США, которая (должна) следовать языковым нормам НАТО, десятичной запятой и т. Д. И мерам ISO) использует ; в качестве разделителя списка для разделения ячеек в электронных таблицах, не путая его с десятичными запятыми.

Таким образом, в общем случае языковые настройки Windows для разделителя списков ;, за исключением английского или американского языка, где разделитель списков ,.

Excel имеет свои неудобства, связанные с американским / английским CSV; В стандартном американском и английском настройках один и тот же символ , является разделителем тысяч, а Excels сходит с ума (ячейки запираются, импортируя CSV с их использованием). Пропуск разделителя тысяч (если он совпадает с разделителем списка) Excel не распознает ячейки валюты и воспринимает их как текст. Что-то, с чем нам приходится жить в США и Англии, в остальном по всему миру это работает нормально (с ;).

Интересная вещь (забавная мысль), если Java в Windows поддерживает NDK с доступом к библиотеке Win32? Потому что в Win32 вы звоните

GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, pwListSeparator, 4); 

Не могу найти решение Java, получающее разделитель списка?

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

Или использовать текстовые файлы с вкладками? Единственное неудобство заключается в том, что Windows по умолчанию открывает Excel для файла .csv и Блокнот для файла .txt с помощью ShellExecute (0, 0, pwFileName, 0, 0 , SW_SHOW) ;.

Примечательно, что в Java существует десятичный разделитель и разделитель тысяч, и я думаю, что следует использовать:

import java.text.DecimalFormatSymbols;
new DecimalFormatSymbols().getDecimalSeparator();
new DecimalFormatSymbols().getGroupingSeparator();
1 голос
/ 16 декабря 2015

Я столкнулся с той же проблемой, а также обнаружил, что единственное правильное решение - предоставить пользователю возможность указать «выбранный разделитель».

Однако, если это невозможно, как это было в моем случае, ближе всего к кроссплатформенной поддержке кросс-локали можно найти следующее:

  • угадайте разделители, которые вам нужно использовать, используя DecimalFormatSymbols
  • добавить строку в начале CSV, содержащую, например, "sep =," (без кавычек), это должно указать разделитель списка, который вы только что догадались

Это, по крайней мере, в большинстве случаев (в тех случаях, которые я тестировал), заставит Excel использовать этот разделитель, даже если вы «угадали», и обеспечит как минимум чуть большую совместимость.

0 голосов
/ 08 мая 2009

Для окон он хранится в реестре по адресу:

"HKEY_CURRENT_USER\\Control Panel\\International"

так что вы можете использовать что-то вроде этого

private void setDelimiterProperties(String delimiter) {
    Properties p = new Properties();
    String key = "HKEY_CURRENT_USER\\Control Panel\\International\\sList";
    p.setProperty(key, delimiter);
}
...