How to read 'List separator' from OS in Ja

2019-01-27 20:31发布

I am writing a CSV exporter in Java that should respect the user's custom settings, especially the "List separator" to use as a delimiter.

In Windows, one can set this List separator in

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

I don't know about the other operating systems, but I'm pretty sure that you can change that on other OSes, too.

What is the best way to get this custom setting from the OS into Java? I am in an Eclipse RCP environment, so I might use RCP-related solutions if there is something available.

7条回答
乱世女痞
2楼-- · 2019-01-27 20:56

Out of curiosity, I searched a bit the topic, and indeed Java seems to have not such notion out of the box.

The Locales Demo gives a fairly complete listing of locale settings and there is no list separator there.

I saw a forum question referring to sun.text.resources package, which is private and deprecated. You won't find much other references to this package, looks like it lives in jre/lib/ext/localedata.jar although my recent copy of this one lists mostly Asian locales.

The above advices are sound, or you might research and use a private list per locale. I would look perhaps at IBM's ICU library (C language I think) which seems to have a fairly big list of locale settings. According to a remark, ICU itself gets its information from a an ISO standard, which should be researched as primary information provider.

查看更多
We Are One
3楼-- · 2019-01-27 21:10

Without resorting to a platform specific solution I think that the best approach to take is going to be to allow users to specify their preference of list separator within your own application. Either in a preferences panel, a dialog box on export or via an optional command line argument.

查看更多
Animai°情兽
4楼-- · 2019-01-27 21:10

For windows it's stored in the registry at:

"HKEY_CURRENT_USER\\Control Panel\\International"

so you can use something like this

private void setDelimiterProperties(String delimiter) {
    Properties p = new Properties();
    String key = "HKEY_CURRENT_USER\\Control Panel\\International\\sList";
    p.setProperty(key, delimiter);
}
查看更多
女痞
5楼-- · 2019-01-27 21:11

In addition to providing your own option to the user in your application you could try to guess what the list separator is.

I had a look at some locales in Windows and saw that the list separator is either ";" or ",". I've heard there is another character in some obscure locale, but have not seen it myself. So if you can make your code to handle both ";" and "," as list separators then you will probably cover majority of cases.

Also, it looks like when "," is used as a decimal separator, then "," is never used as a list separator. I guess this is otherwise numbers will be impossible to distinguish in a list: 1,2,3,4 could be 1.2, 3.4 or 1, 2.3 In these cases ";" is used as a list separator. Unfortunately the reverse is not true. Arabic has "." as a decimal symbol and ";" as a list separator.

So I think the rule that can be reasonably safely followed is:

if (decimalSeparator == ',') 
    then listSeparator = ';'
else if (decimalSeparator == '.') 
    then listSeparator = new char[] {';', ','}
查看更多
太酷不给撩
6楼-- · 2019-01-27 21:15

I faced the same problem and also found out that the only proper solution is to provide a way to the user to specify the "delimiter of choice".

However, if that is not possible, as it was in my case, the closest I could get to cross-platfrom, cross-locale support is the following:

  • guess the separators you need to use using DecimalFormatSymbols
  • add a line at the beginning of the CSV containing, for example "sep=," (without quotes), this should specify the list separator you've just guessed

This will, at least in most cases (the cases I have tested), force Excel to use that delimiter, even if you "guessed wrong" and will provide at least a little bit more compatibility.

查看更多
小情绪 Triste *
7楼-- · 2019-01-27 21:16

Well I see this as a serious topic!

Thing is that in Windows, there is the Excel. And many programs have to interact with it. Excel uses the List separator locale (cell separation).

The basic problem is that “Comma Separated Values” do not work outside US (Spanish (USA)) and English because you can’t have the same list separator character as the decimal separator. So the world outside US and English (including US army that (should) follow NATO locales, decimal comma etc and ISO measures) uses ; as list separator to separate cells in spreadsheets, not confusing it with the decimal commas.

So in general, the locale Windows settings for list separator is ; except for English or US where list separator is , .

Excel has its US/English CSV inconveniences, specifically; In the default US and English settings the same character (,) is thousand separator and Excels goes nuts (cells gets screwed importing CSVs with it used). Skipping thousand separator (when it is the same as the list separator) Excel do not recognise currency cells and take them as text. Something we have to live with in US and English environments, else world wide it works fine (with ; ).

Interesting thing (funny thought) is if Java in Windows supports an NDK with Win32 library access? Because in Win32 you call

GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, pwListSeparator, 4); 

I can’t find a Java solution getting a list separator?

My suggestion is using hard coded general rule, set the list separator to ; when decimal separator is , else set the list separator to , if another character can't be found in the locale methods or settings like in Win32. Remove (don't use) thousand separators if they are the same as the list separator.

Or use tabbed text files? The only inconvenience is that Windows open by default Excel on a .csv file and Notepad on a .txt file using the ShellExecute(0, 0, pwFileName, 0, 0, SW_SHOW);.

Noticeable is that decimal separator and thousand separator exists in Java and I guess should be used:

import java.text.DecimalFormatSymbols;
new DecimalFormatSymbols().getDecimalSeparator();
new DecimalFormatSymbols().getGroupingSeparator();
查看更多
登录 后发表回答