从电话号码中提取国家代码 [libphonenumber]

98

我有一个这样的字符串:+33123456789(法国电话号码)。我想提取国家代码(+33),但不知道国家。例如,如果我有另一个来自其他国家的电话,它也应该能工作。我使用谷歌库https://code.google.com/p/libphonenumber/

如果我知道国家,那就很酷了,我可以找到国家代码:

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
int countryCode = phoneUtil.getCountryCodeForRegion(locale.getCountry());

但是我找不到一种方法来解析一个字符串而不知道国家。


可能是使用Android获取电话国家代码的重复问题。 - Simon
请参阅https://dev59.com/KnE85IYBdhLWcg3w9odJ。 - Simon
1
第一个链接是基于电话国家代码的。但在我的情况下,我可能会有一个既有法国电话号码又有英国电话号码的字符串。因此,如果我检索当前区域设置,我将得到“EN”,但我的字符串将是一个法国国家代码。 - mrroboaat
@Simon,我知道这是一个旧帖子,但我认为你提到的两个问题并不重复。干杯。 - Bink
7个回答

150

好的,所以我已经加入了libphonenumber的谷歌群组(https://groups.google.com/forum/?hl=en&fromgroups#!forum/libphonenumber-discuss)并提出了一个问题。

如果我的电话号码以"+"开头,我就不需要在参数中设置国家。这里有一个例子:

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
    // phone must begin with '+'
    PhoneNumber numberProto = phoneUtil.parse(phone, "");
    int countryCode = numberProto.getCountryCode();
} catch (NumberParseException e) {
    System.err.println("NumberParseException was thrown: " + e.toString());
}

7
这个疯狂的图书馆非常神奇,比Android自带的PhoneNumberUtil库好亿倍。 - Aphex
1
@Shweta 如果你有问题,请在 SO 上发布一个新的线程。 - mrroboaat
1
@aat 好的,但是你的答案不正确,如果没有提供任何 countryISOCode,这段代码将无法执行。 - Ash
4
@Schweta 默认区域参数应该为 null:defaultRegion是ISO 3166-1两位字母地区代码,用于表示我们期望号码来自的地区。仅在被解析的号码未以国际格式书写时使用。在这种情况下,号码的国家代码将存储为提供的默认区域的国家代码。如果保证号码以“+”加上国家呼叫代码开头,则可以提供“ZZ”或null作为国家代码。 - xnagyg
1
如果我需要将电话簿中的电话号码解析为E164格式,并且手机所在地可能会更改(例如,当手机用户前往其他国家时),我该怎么办?我也知道大多数号码不是以+.....的格式书写的。 - user2924714
显示剩余3条评论

4

我有一个方便的辅助方法可以处理这个问题,基于上面一篇答案:

导入:

import com.google.i18n.phonenumbers.NumberParseException
import com.google.i18n.phonenumbers.PhoneNumberUtil

功能:

    fun parseCountryCode( phoneNumberStr: String?): String {
        val phoneUtil = PhoneNumberUtil.getInstance()
        return try {
            // phone must begin with '+'
            val numberProto = phoneUtil.parse(phoneNumberStr, "")
            numberProto.countryCode.toString()
        } catch (e: NumberParseException) {
            ""
        }
    }

3
在这里,您可以将电话号码保存为国际格式的电话号码。
internationalFormatPhoneNumber = phoneUtil.format(givenPhoneNumber, PhoneNumberFormat.INTERNATIONAL);

IT会将电话号码返回为国际格式 +94 71 560 4888。

现在,我已获取了该国家的区号。

String countryCode = internationalFormatPhoneNumber.substring(0,internationalFormatPhoneNumber.indexOf('')).replace('+', ' ').trim();

希望这能对你有所帮助


1
internationalFormatPhoneNumber 是什么数据类型,以及 phoneUtil 是什么? - Kartheek Sarabu
1
给定的电话号码参数不是字符串,它必须是已解析的电话号码,在其中您需要默认区域来生成。 - Gil SH
@GilSH 是的,givenPhoneNumber 不是字符串,而是 PhoneNumber 对象。 - Thilina Rubasingha
1
这个答案对我很有帮助。 - luttu android
给定的电话号码是什么? - TharakaNirmana
这取决于国家代码和电话号码的其余部分之间是否存在空格。它无法处理字符串“+94715604888”。 - Flimm

1
这里提供了一种方法,可以根据国际电话号码获取国家信息,而不需要使用Google库。
首先,让我解释一下为什么很难确定所在的国家。有些国家的国家代码只有1、2、3或4位数字,这本来很简单。但是,国家代码1不仅用于美国,还用于加拿大和其他一些小地方:
1339 美国
1340 维京群岛(加勒比海岛屿)
1341 美国
1342 未使用
1343 加拿大
数字2到4决定它是否为美国、加拿大等。没有简单的方法可以确定国家,例如前三个数字是加拿大,后面的是美国。
对于我的代码,我定义了一个类,保存每个数字的信息。
public class DigitInfo {
  public char Digit;
  public Country? Country;
  public DigitInfo?[]? Digits;
}

第一个数组保存了数字中的第一个数字的DigitInfos。第二个数字用作DigitInfo.Digits的索引。沿着该Digits链向下移动,直到Digits为空为止。如果定义了Country(即不为null),则返回该值,否则返回之前定义的任何Country:

country code 1: byPhone[1].Country is US  
country code 1236: byPhone[1].Digits[2].Digits[3].Digits[6].Country is Canada  
country code 1235: byPhone[1].Digits[2].Digits[3].Digits[5].Country is null. Since   
                   byPhone[1].Country is US, also 1235 is US, because no other   
                   country was found in the later digits

这是一个根据电话号码返回国家的方法:
/// <summary>
/// Returns the Country based on an international dialing code.
/// </summary>
public static Country? GetCountry(ReadOnlySpan<char> phoneNumber) {
  if (phoneNumber.Length==0) return null;

  var isFirstDigit = true;
  DigitInfo? digitInfo = null;
  Country? country = null;
  foreach (var digitChar in phoneNumber) {
    var digitIndex = digitChar - '0';
    if (isFirstDigit) {
      isFirstDigit = false;
      digitInfo = ByPhone[digitIndex];
    } else {
      if (digitInfo!.Digits is null) return country;

      digitInfo = digitInfo.Digits[digitIndex];
    }
    if (digitInfo is null) return country;

    country = digitInfo.Country??country;
  }
  return country;
}

其余的代码(世界各国的digitInfos,测试代码等)太大了,无法在此处发布,但可以在Github上找到:https://github.com/PeterHuberSg/WpfWindowsLib/blob/master/WpfWindowsHelperLib/CountryCode.cs 该代码是WPF TextBox的一部分,该库还包含其他控件,用于电子邮件地址等。更详细的描述在CodeProject上:详细解释国际电话号码验证 更改23.1.23:我将CountryCode.cs移动到WpfWindowsHelperLib中,尽管它的名称如此,但它没有任何WPF依赖项。

我的 git 链接无法使用。 - msarafzadeh
抱歉,我将它移动到同一解决方案中的另一个库中,以消除对WPF的任何依赖。 - Peter Huber

0
请使用以下的try catch块:
try { 

const phoneNumber = this.phoneUtil.parseAndKeepRawInput(value, this.countryCode);

}catch(e){}

-6
如果包含电话号码的字符串始终以此方式开始(+33或其他国家代码),则应使用正则表达式解析并获取国家代码,然后使用库获取与该号码相关联的国家。

存在许多不同的国家代码:http://en.wikipedia.org/wiki/List_of_country_calling_codes - mrroboaat

-28

以下是如何在不使用第三方库的情况下查找国家区号的答案(正如真正的开发人员所做的那样):

获取所有可用国家代码列表,可以通过维基百科获得帮助: https://en.wikipedia.org/wiki/List_of_country_calling_codes

将数据解析成树形结构,其中每个数字都是一个分支。

逐位遍历您的树,直到您到达最后一个分支-那就是您的国家代码。


38
我因这条评论“这里有一种方法可以找到国家呼叫代码,而不使用第三方库(像真正的开发者一样)”而将它点踩。你认为软件为什么会进步?因为人们不必每次都重新发明轮子。真正聪明的开发者使用第三方库。 - Carl B
2
你的个人观点并不能证明我的答案是错误的,对吧?事实上,这是目前唯一正确和无懈可击的答案...而且,它不需要任何第三方软件才能运行。如果你坚持使用第三方库,欢迎购买我的解决方案。 - Unobic
2
更新库比不断地去维基百科页面检查国家区号列表是否更改要容易得多。 - Flimm
1
@Unobic 抱歉啊,他们不应该因为个人观点在Stackoverflow上投票。我在搜索时正好在寻找你的答案。所以谢谢你。至少我给你点赞了。 - Ybrin
踩票不是针对技术内容,而是针对那个非常不必要的说法“像真正的开发者一样”。甚至在语法上都是错误的。很难理解为什么作者不会删除这个说法。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接