是否有 ISO3166-1国家代码的开源 java 枚举

有没有人知道一个可以免费获得的 java 1.5包,它提供了一个作为 enum 或 EnumMap 的 ISO 3166-1国家代码列表?具体来说,我需要“ ISO3166-1-alpha-2代码元素”,即2个字符的国家代码,如“ us”、“ uk”、“ de”等。创建一个非常简单(尽管很乏味) ,但是如果在阿帕奇之地或类似的地方已经有一个标准的,那么它将节省一点时间。

99895 次浏览

This code gets 242 countries in Sun Java 6:

String[] countryCodes = Locale.getISOCountries();

Though the ISO website claims there are 249 ISO 3166-1-alpha-2 code elements, though the javadoc links to the same information.

There is an easy way to generate this enum with the language name. Execute this code to generate the list of enum fields to paste :

 /**
* This is the code used to generate the enum content
*/
public static void main(String[] args) {
String[] codes = java.util.Locale.getISOLanguages();
for (String isoCode: codes) {
Locale locale = new Locale(isoCode);
System.out.println(isoCode.toUpperCase() + "(\"" + locale.getDisplayLanguage(locale) + "\"),");
}
}

Here's how I generated an enum with country code + country name:

package countryenum;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;


public class CountryEnumGenerator {
public static void main(String[] args) {
String[] countryCodes = Locale.getISOCountries();
List<Country> list = new ArrayList<Country>(countryCodes.length);


for (String cc : countryCodes) {
list.add(new Country(cc.toUpperCase(), new Locale("", cc).getDisplayCountry()));
}


Collections.sort(list);


for (Country c : list) {
System.out.println("/**" + c.getName() + "*/");
System.out.println(c.getCode() + "(\"" + c.getName() + "\"),");
}


}
}


class Country implements Comparable<Country> {
private String code;
private String name;


public Country(String code, String name) {
super();
this.code = code;
this.name = name;
}


public String getCode() {
return code;
}




public void setCode(String code) {
this.code = code;
}




public String getName() {
return name;
}




public void setName(String name) {
this.name = name;
}




@Override
public int compareTo(Country o) {
return this.name.compareTo(o.name);
}
}

This still does not answer the question. I was also looking for a kind of enumerator for this, and did not find anything. Some examples using hashtable here, but represent the same as the built-in get

I would go for a different approach. So I created a script in python to automatically generate the list in Java:

#!/usr/bin/python
f = open("data.txt", 'r')
data = []
cc = {}


for l in f:
t = l.split('\t')
cc = { 'code': str(t[0]).strip(),
'name': str(t[1]).strip()
}
data.append(cc)
f.close()


for c in data:
print """
/**
* Defines the <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO_3166-1_alpha-2</a>
* for <b><i>%(name)s</i></b>.
* <p>
* This constant holds the value of <b>{@value}</b>.
*
* @since 1.0
*
*/
public static final String %(code)s = \"%(code)s\";""" % c

where the data.txt file is a simple copy&paste from Wikipedia table (just remove all extra lines, making sure you have a country code and country name per line).

Then just place this into your static class:

/**
* Holds <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO_3166-1_alpha-2</a>
* constant values for all countries.
*
* @since 1.0
*
* </p>
*/
public class CountryCode {


/**
* Constructor defined as <code>private</code> purposefully to ensure this
* class is only used to access its static properties and/or methods.
*/
private CountryCode() { }


/**
* Defines the <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO_3166-1_alpha-2</a>
* for <b><i>Andorra</i></b>.
* <p>
* This constant holds the value of <b>{@value}</b>.
*
* @since 1.0
*
*/
public static final String AD = "AD";


//
// and the list goes on! ...
//
}

Now an implementation of country code (ISO 3166-1 alpha-2/alpha-3/numeric) list as Java enum is available at GitHub under Apache License version 2.0.

Example:

CountryCode cc = CountryCode.getByCode("JP");


System.out.println("Country name = " + cc.getName());                // "Japan"
System.out.println("ISO 3166-1 alpha-2 code = " + cc.getAlpha2());   // "JP"
System.out.println("ISO 3166-1 alpha-3 code = " + cc.getAlpha3());   // "JPN"
System.out.println("ISO 3166-1 numeric code = " + cc.getNumeric());  // 392

Last Edit 2016-Jun-09

CountryCode enum was packaged into com.neovisionaries.i18n with other Java enums, LanguageCode (ISO 639-1), LanguageAlpha3Code (ISO 639-2), LocaleCode, ScriptCode (ISO 15924) and CurrencyCode (ISO 4217) and registered into the Maven Central Repository.

Maven

<dependency>
<groupId>com.neovisionaries</groupId>
<artifactId>nv-i18n</artifactId>
<version>1.29</version>
</dependency>

Gradle

dependencies {
compile 'com.neovisionaries:nv-i18n:1.29'
}

GitHub

https://github.com/TakahikoKawasaki/nv-i18n

Javadoc

https://takahikokawasaki.github.io/nv-i18n/

OSGi

Bundle-SymbolicName: com.neovisionaries.i18n
Export-Package: com.neovisionaries.i18n;version="1.28.0"

I didn't know about this question till I had just recently open-sourced my Java enum for exactly this purpose! Amazing coincidence!

I put the whole source code on my blog with BSD caluse 3 license so I don't think anyone would have any beefs about it.

Can be found here. https://subversivebytes.wordpress.com/2013/10/07/java-iso-3166-java-enum/

Hope it is useful and eases development pains.

If you are already going to rely on Java locale, then I suggest using a simple HashMap instead of creating new classes for countries etc.

Here's how I would use it if I were to rely on the Java Localization only:

private HashMap<String, String> countries = new HashMap<String, String>();
String[] countryCodes = Locale.getISOCountries();


for (String cc : countryCodes) {
// country name , country code map
countries.put(new Locale("", cc).getDisplayCountry(), cc.toUpperCase());
}

After you fill the map, you can get the ISO code from the country name whenever you need it. Or you can make it a ISO code to Country name map as well, just modify the 'put' method accordingly.

Not a java enum, but a JSON version of this is available at http://country.io/names.json

If anyone is already using the Amazon AWS SDK it includes com.amazonaws.services.route53domains.model.CountryCode. I know this is not ideal but it's an alternative if you already use the AWS SDK. For most cases I would use Takahiko's nv-i18n since, as he mentions, it implements ISO 3166-1.

I have created an enum, which you address by the english country name. See country-util.
On each enum you can call getLocale() to get the Java Locale.

From the Locale you can get all the information you are used to, fx the ISO-3166-1 two letter country code.

public enum Country{


ANDORRA(new Locale("AD")),
AFGHANISTAN(new Locale("AF")),
ANTIGUA_AND_BARBUDA(new Locale("AG")),
ANGUILLA(new Locale("AI")),
//etc
ZAMBIA(new Locale("ZM")),
ZIMBABWE(new Locale("ZW"));


private Locale locale;


private Country(Locale locale){
this.locale = locale;
}


public Locale getLocale(){
return locale;
}

Pro:

  • Light weight
  • Maps to Java Locales
  • Addressable by full country name
  • Enum values are not hardcoded, but generated by a call to Locale.getISOCountries(). That is: Simply recompile the project against the newest java version to get any changes made to the list of countries reflected in the enum.

Con:

  • Not in Maven repository
  • Most likely simpler / less expressive than the other solutions, which I don't know.
  • Created for my own needs / not as such maintained. - You should probably clone the repo.

AWS Java SDK has CountryCode.

There is standard java.util.Locale.IsoCountryCode since Java 9.

I found the IsoCountry list here, it has 2 and 3 char country codes