Java电话号码格式API
我有一个数据库,里面有数百万个电话号码,所有格式都是免费的。也就是说,用户界面不强制任何约束,用户输入他们想要的任何内容 我要寻找的是一个JavaAPI,它可以尽最大努力将这些转换为一致的格式。理想情况下,API将获取自由文本值和国家代码,并生成有效的国际电话号码或引发异常 例如,系统中的电话号码可能类似于以下任何一种:Java电话号码格式API,java,Java,我有一个数据库,里面有数百万个电话号码,所有格式都是免费的。也就是说,用户界面不强制任何约束,用户输入他们想要的任何内容 我要寻找的是一个JavaAPI,它可以尽最大努力将这些转换为一致的格式。理想情况下,API将获取自由文本值和国家代码,并生成有效的国际电话号码或引发异常 例如,系统中的电话号码可能类似于以下任何一种: (555) 478-1123 555-478-1123 555.478.1123 5554781123 Iterable<PhoneNumberMatch>
(555) 478-1123
555-478-1123
555.478.1123
5554781123
Iterable<PhoneNumberMatch> numbers = PhoneNumberUtil.getInstance().findNumbers(textWithPhoneNums, "FR");
for(Iterator<PhoneNumberMatch> iterator = numbers.iterator(); iterator.hasNext(); ){
PhoneNumberMatch pnm = iterator.next();
PhoneNumber number = pnm.number();
System.out.println(PhoneNumberUtil.getInstance().formatOutOfCountryCallingNumber(number, null));
}
考虑到我们的国家,API将为所有这些产生+1 555 478-1123的值。确切的格式并不重要,只要是一致的
系统中也有没有区号的号码,如478-1123。在这种情况下,我希望出现一个异常或类似的情况
也可能有像abc这样的数据,它也会抛出异常
当然,我发布的示例有无数种变体,国际电话号码的复杂性也非常大,其验证规则相当复杂。这就是为什么我不考虑滚动自己。
有人见过这样的API吗?我不知道有这样的API,但它看起来可以通过使用正则表达式来实现。可能您无法将所有号码转换为有效格式,但大多数号码都是有效格式。有一些商业程序可以对国际电话号码进行格式化和验证,例如在某些国家甚至可以检查有效的区号。对于北美,提供了验证区号的功能。您可以编写自己的For US电话格式: 从字符串中删除任何非数字字符 检查剩余字符串的长度是否为10个字符 在前三个字符周围加括号,在第六个和第七个字符之间加破折号。 在字符串前加上+1 更新:
谷歌最近发布了一个用于解析、格式化、存储和验证国际电话号码的软件。我认为没有办法确认没有区号,除非你的号码都来自一个国家,大概是美国,因为每个国家都有自己的区号规则 我会开始寻找详细的信息,如果有API用Java或其他方式处理它,它们可能也会链接到那里。我发现最好的是javax.telephony,可以在这里找到: 它有一个Address类,但遗憾的是该类并没有解决您的问题: 好吧,也许你可以通过深入研究找到解决办法
除此之外,我的第一个想法是使用正则表达式。然而,对于这个特定的问题,这似乎是一种糟糕的解决方案。您可以尝试使用这个Java电话号码格式化库 它有数百个国家和格式的数据。的最新版本为许多新国家添加了元数据,并为先前列出的一些国家添加了更多详细信息 当前的源代码版本是r74,而.jar文件的版本是2.6。以前的.jar文件是为Java1.6编译的,但是从libphonenumber版本2.5.1开始,它们现在是为Java1.5和更高版本编译的 别忘了还有一个JavaScript代码的直接端口。可以在以下位置的源代码树中找到它:
欢迎提供Bug报告。积极鼓励更新元数据,因为即使是许多国家的官方政府公布的区号清单也不完整或过时 对于看起来像01 44 55 66 77的法语数字,我们可以使用以下逻辑
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setGroupingSeparator(' '); // sometimes '.' is used
DecimalFormat decfmt = new DecimalFormat("0,0", dfs); // enable grouping
decfmt.setMinimumIntegerDigits(10); // we always have 10 digits
decfmt.setGroupingSize(2); // necessary in order to group digits by 2 orders
System.out.println(decfmt.format(144556677)); // outputs "01 44 55 66 77"
一旦可以做到这一点,使用谷歌的电话号码API,我们可以轻松解析这些序列,并将其重新格式化为其他形式,如+33 1 44 55 66 77,如下所示:
(555) 478-1123
555-478-1123
555.478.1123
5554781123
Iterable<PhoneNumberMatch> numbers = PhoneNumberUtil.getInstance().findNumbers(textWithPhoneNums, "FR");
for(Iterator<PhoneNumberMatch> iterator = numbers.iterator(); iterator.hasNext(); ){
PhoneNumberMatch pnm = iterator.next();
PhoneNumber number = pnm.number();
System.out.println(PhoneNumberUtil.getInstance().formatOutOfCountryCallingNumber(number, null));
}
简单正则表达式解析器
总体安排
我根据我的需要做了这个,它接受数字:
国家代码
数字
国家代码:
它们可能有一个:+,或者一个或两个零。
然后,它后面可能跟一个-
接受:
+456
00456
+1234
01234
以上所有内容可能会或可能不会出现-
拒绝:
0456
应该是:
00456或+456或04444
数字
一个8-20位的简单数字
接受:
00456-12345678
+457-12345678
+45712345678
0045712345678
99999999
扩展它?
请随意,以便您可以包括对的支持。或分离器。只要确保你避开它们,例如,为了使用\。我自己的需求非常简单。我只需要取一个7或10位数的数字,在区号、交换号和交换号之间加一个破折号、句号、一些字符串等分隔符。任何传入方法的值,如果不是全部数字或长度不是7或10,则只返回。空值返回空字符串,分隔符的空值被视为空字符串。我的代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// ...
private String formatPhoneNumber(String phnumber, String separator) {
phnumber = (phnumber == null) ? "" : phnumber;
if ((phnumber.length() != 7) && (phnumber.length() != 10)) { return phnumber; }
// If we get here, 'phnumber' is for sure either 7 or 10 chars long
separator = (separator == null) ? "" : separator;
Pattern p = Pattern.compile("([0-9]*)");
Matcher m = p.matcher(phnumber);
if (m.matches()) {
if (phnumber.length() == 7) {
return phnumber.substring(0, 3) + separator + phnumber.substring(4);
} else {
return phnumber.substring(0, 3) + separator + phnumber.substring(3, 6)
+ separator + phnumber.substring(6);
}
// If we get here, it means 1 or more of the chars in 'phnumber'
// is not a digit and so 'phnumber' is returned just as passed in.
return phnumber;
}
不要重新发明轮子;使用API,例如。 这个API也提供了很好的格式。 例如: 您甚至可以使用phoneNumber对象来创建ni
cely在将其保存到DB或其他任何地方之前将其格式化为有效的电话号码。我使用libphonenumber创建了一个Helper类,但这仍然是可能的,即用户大多将本地联系人中的本地号码保存为本地格式,我的意思是没有国家代码,因为它是本地号码,但将使用国家代码保存国际号码。这个助手适用于这两种情况,如果数字是全局格式的,它将保持原样,同时将本地数字转换为内部格式。下面是代码和用法
class PhoneNumberHelper {
companion object {
fun correctNumber(number: String, context: Context): String? {
val code = StorageAdapter.get(context).userCountryCode
return validateNumber(number, code)
}
private fun validateNumber(number: String, mUserCountryCode: Int): String? {
return Utils.formatNumber(Utils.removeDelimetersFromNumber(number), mUserCountryCode)
}
fun formatNumber(destinationNumber: String, countryCode: Int): String? {
try {
val phoneUtil = PhoneNumberUtil.getInstance()
val regionCode = phoneUtil.getRegionCodeForCountryCode(countryCode)
var formattedNumber = formatNumber(destinationNumber, regionCode)
if (TextUtils.isEmpty(formattedNumber)) {
formattedNumber = destinationNumber
}
return formattedNumber
} catch (exp: Exception) {
Log.e("formatNumber", exp.toString())
}
return destinationNumber
}
fun formatNumber(destinationNumber: String, regionCode: String): String? {
if (TextUtils.isEmpty(regionCode)) {
return null
}
var number: String? = null
try {
val phoneUtil = PhoneNumberUtil.getInstance()
val phoneNumber = phoneUtil.parse(destinationNumber, regionCode)
if (phoneUtil.isValidNumber(phoneNumber)) {
/*
* E164 format is as per international format but no
* formatting applied e.g. no spaces in between
*/
number = phoneUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164)
number = number!!.replace("+", "00")
}
} catch (e: Exception) {
// number would be returned as null if it catches here
}
return number
}
}
}
以下是您将如何使用它:
var globalnumber = PhoneNumberHelper.correctNumber(contact.mobile, context)
澄清:
val code = StorageAdapter.get(context).userCountryCode
这是您在注册时应存储的国家代码。e、 g.0044或+44
不要忘记包含libphone的依赖项:
implementation 'com.googlecode.libphonenumber:libphonenumber:8.8.0'
这就是让我不敢尝试自己的想法的原因。看看澳大利亚的电话号码规则:这适用于美国的电话号码。我也希望有一个通用的国际解决方案,我理解。你必须为你感兴趣的每个国家实施一个单独的格式方法,使用不同的电话号码格式。这基本上就是我最后要做的。您可以从我的博客中下载一些美国和英国电话号码的示例代码:@Chase:谢谢您的发布。libphonenumber要求您已经知道国家代码,以便能够执行任何有用的操作。是的,这就是为什么我认为API应该采用国家代码参数的原因。到目前为止,PERL API是我见过的最好的。我个人不会使用它,因为它是商业性的和非Java的,但对于某些项目来说它会非常好。这将是一个很酷的功能,可以包含在Java Phone API规范中,但我同意它现在不这样做。我想补充一个后续问题,但是我自己问了一个相关的问题,以避免劫持你的问题。非常拖拉的Shevrin,首先-有一个api用于将代码模式形式化并抽象为比循环这些字符更一般的形式,在这里插入空格。。。等其次,将正确的国际化格式应用于电话号码并非易事。