如何在Java中验证葡萄牙式欧洲数字格式?
葡萄牙式欧洲数字格式验证问题
有效格式示例
1.234,561 234,56(单个空格作为千位分隔符)1.234.567,891 234 567,89(单个空格作为千位分隔符)1 234,56(多空格可替换为单个空格,属于常见手写格式)
无效格式示例
1,234.56(误用英文格式分隔符)1.234 56(空格用作小数点分隔符)1,234,567.89(英文格式)1 234.56(多空格且小数点格式错误)
问题与现有代码
我需要验证这类葡萄牙式欧洲数字格式,但自己尝试模式匹配效果不好,有没有可用的第三方库?另外我写了一段代码,可能存在问题,代码如下:
import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParseException; import java.util.Locale; import java.util.Objects; public class ValidateEuropeanNumber { /** * Checks if the input string represents a valid European number format. * * Preconditions: * - The input string must not be null. * * Postconditions: * - Returns true if the input string represents a valid European number format. * - Returns false if the input string does not represent a valid European number format. * * @param input The string to check for a valid European number format. * @return true if the input string represents a valid European number format, false otherwise. * @throws NullPointerException if the input string is null. */ public static boolean isValidEuropeanNumber(String input) { Objects.requireNonNull(input, "The input string must not be null."); // Remove leading and trailing spaces input = input.trim(); // Replace multiple spaces with a single space input = input.replaceAll("\\s{2,}", " "); DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.GERMAN); DecimalFormat format = new DecimalFormat("#,##0.###", symbols); format.setParseBigDecimal(true); try { BigDecimal number = (BigDecimal) format.parse(input); // Check if there are any periods in the input if (input.contains(".")) { DecimalFormatSymbols periodSymbols = new DecimalFormatSymbols(Locale.UK); DecimalFormat periodFormat = new DecimalFormat("#,##0.###", periodSymbols); periodFormat.setParseBigDecimal(true); BigDecimal periodNumber = (BigDecimal) periodFormat.parse(input); } return true; } catch (ParseException e) { return false; } } }
现有代码问题
这段代码有几个明显问题:
- 用了
Locale.GERMAN的格式符号,但葡萄牙的数字格式和德语区不同,应该用葡萄牙本地语言环境 - 额外的英文格式解析逻辑会把无效的英文格式(比如
1,234.56)误判为有效 DecimalFormat默认不开启严格解析,会忽略部分格式错误,导致误判
改进后的原生代码实现
不需要第三方库的话,可以调整代码适配葡萄牙格式,同时开启严格解析:
import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParsePosition; import java.util.Locale; import java.util.Objects; public class ValidateEuropeanNumber { /** * 检查输入字符串是否为有效的葡萄牙式欧洲数字格式 * * @param input 待检查的字符串 * @return 有效返回true,无效返回false * @throws NullPointerException 如果输入为null */ public static boolean isValidPortugueseNumber(String input) { Objects.requireNonNull(input, "输入字符串不能为空"); // 处理首尾空格,把多个空格替换成单个空格 String cleanedInput = input.trim().replaceAll("\\s{2,}", " "); // 统一把空格千位分隔符替换成.,适配葡萄牙格式的解析规则 String normalizedInput = cleanedInput.replace(' ', '.'); // 使用葡萄牙(葡萄牙语)的格式符号:千位分隔符是.,小数点是, DecimalFormatSymbols ptSymbols = new DecimalFormatSymbols(Locale.forLanguageTag("pt-PT")); // 定义格式:整数部分至少一位,千位用.分隔,小数部分最多三位 DecimalFormat format = new DecimalFormat("#,##0.###", ptSymbols); format.setParseBigDecimal(true); // 开启严格解析,必须完全匹配格式 format.setParseStrict(true); ParsePosition pos = new ParsePosition(0); format.parse(normalizedInput, pos); // 只有整个字符串都被解析完成,才判定为有效 return pos.getIndex() == normalizedInput.length(); } }
关键优化点
- 用
Locale.forLanguageTag("pt-PT")匹配葡萄牙本地数字格式规则 - 先统一处理空格分隔符,把空格替换成
.,避免解析不兼容 - 开启严格解析模式,确保格式完全符合要求
- 用
ParsePosition检查解析是否覆盖整个字符串,防止部分有效但整体无效的情况
第三方库方案
如果想简化开发,可以用Apache Commons Lang或者ICU4J这类成熟的工具库:
Apache Commons Lang 示例
import org.apache.commons.lang3.math.NumberUtils; import java.util.Locale; import java.util.Objects; public class ValidateWithCommons { public static boolean isValidPortugueseNumber(String input) { Objects.requireNonNull(input, "输入字符串不能为空"); String cleaned = input.trim().replaceAll("\\s{2,}", " ").replace(' ', '.'); // 使用葡萄牙语环境解析,确保格式匹配 return NumberUtils.isParsable(cleaned, Locale.forLanguageTag("pt-PT")); } }
需要引入Maven依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.14.0</version> </dependency>
内容的提问来源于stack exchange,提问作者Tushar
相关产品推荐
相关产品推荐

