package com.ruoyi.common.utils; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; public class ChineseUtils { private static final String[] CN_NUM = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; private static final String[] CN_UNIT = { "", "拾", "佰", "仟" }; private static final String[] CN_BIG_UNIT = { "", "万", "亿", "兆" }; private static final Map CN_NUM_MAP = new HashMap<>(); private static final Map CN_UNIT_MAP = new HashMap<>(); static { for (int i = 0; i < CN_NUM.length; i++) { CN_NUM_MAP.put(CN_NUM[i].charAt(0), i); } CN_NUM_MAP.put('零', 0); CN_NUM_MAP.put('一', 1); CN_NUM_MAP.put('二', 2); CN_NUM_MAP.put('三', 3); CN_NUM_MAP.put('四', 4); CN_NUM_MAP.put('五', 5); CN_NUM_MAP.put('六', 6); CN_NUM_MAP.put('七', 7); CN_NUM_MAP.put('八', 8); CN_NUM_MAP.put('九', 9); CN_NUM_MAP.put('两', 2); CN_UNIT_MAP.put('拾', 10); CN_UNIT_MAP.put('佰', 100); CN_UNIT_MAP.put('仟', 1000); CN_UNIT_MAP.put('十', 10); CN_UNIT_MAP.put('百', 100); CN_UNIT_MAP.put('千', 1000); } /** * 校验是否是中文 * * @param str * @return */ public static boolean isChinese(String str) { for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (isChineseCharacter(c)) { return true; } } return false; } private static boolean isChineseCharacter(char c) { // 汉字的Unicode编码范围是0x4E00到0x9FA5 return c >= 0x4E00 && c <= 0x9FA5; } /** * 数字金额转中文大写 * 例如:1234.56 -> 壹仟贰佰叁拾肆元伍角陆分 */ public static String numberToChinese(BigDecimal amount) { if (amount == null) { throw new IllegalArgumentException("金额不能为空"); } boolean negative = amount.signum() < 0; amount = amount.abs().setScale(2, BigDecimal.ROUND_HALF_UP); long integerPart = amount.longValue(); int decimalPart = amount.subtract(new BigDecimal(integerPart)) .multiply(new BigDecimal(100)) .intValue(); int jiao = decimalPart / 10; int fen = decimalPart % 10; StringBuilder sb = new StringBuilder(); if (negative) { sb.append("负"); } if (integerPart == 0) { sb.append("零元"); } else { sb.append(integerToChinese(integerPart)).append("元"); } if (jiao == 0 && fen == 0) { sb.append("整"); } else { if (jiao > 0) { sb.append(CN_NUM[jiao]).append("角"); } else if (fen > 0 && integerPart > 0) { sb.append("零"); } if (fen > 0) { sb.append(CN_NUM[fen]).append("分"); } } return sb.toString(); } public static String numberToChinese(double amount) { return numberToChinese(BigDecimal.valueOf(amount)); } public static String numberToChinese(String amount) { return numberToChinese(new BigDecimal(amount)); } /** * 整数部分转中文大写 */ private static String integerToChinese(long num) { if (num == 0) { return "零"; } StringBuilder sb = new StringBuilder(); int unitIndex = 0; boolean needZero = false; while (num > 0) { int section = (int) (num % 10000); if (section != 0) { String sectionStr = sectionToChinese(section); if (needZero || (section < 1000 && sb.length() > 0)) { sb.insert(0, "零"); } sb.insert(0, sectionStr + CN_BIG_UNIT[unitIndex]); needZero = section < 1000; } else { if (sb.length() > 0 && !sb.toString().startsWith("零")) { needZero = true; } } num /= 10000; unitIndex++; } String result = sb.toString(); result = result.replaceAll("零+", "零"); result = result.replaceAll("零$", ""); result = result.replaceAll("零万", "万"); result = result.replaceAll("零亿", "亿"); return result; } /** * 四位以内数字转中文 */ private static String sectionToChinese(int section) { StringBuilder sb = new StringBuilder(); int unit = 1000; boolean zeroFlag = false; while (section > 0) { int digit = section / unit; if (digit == 0) { if (sb.length() > 0 && !zeroFlag) { zeroFlag = true; sb.append("零"); } } else { zeroFlag = false; sb.append(CN_NUM[digit]).append(CN_UNIT[getUnitIndex(unit)]); } section %= unit; unit /= 10; } String result = sb.toString(); if (result.endsWith("零")) { result = result.substring(0, result.length() - 1); } return result; } private static int getUnitIndex(int unit) { switch (unit) { case 1000: return 3; case 100: return 2; case 10: return 1; default: return 0; } } /** * 中文大写金额转数字 * 例如:壹仟贰佰叁拾肆元伍角陆分 -> 1234.56 */ public static BigDecimal chineseToNumber(String chinese) { if (chinese == null || chinese.trim().isEmpty()) { throw new IllegalArgumentException("中文金额不能为空"); } String str = chinese.trim() .replace("整", "") .replace("正", "") .replace("人民币", ""); boolean negative = str.startsWith("负"); if (negative) { str = str.substring(1); } // 分离元、角、分 String integerPartStr; String decimalPartStr = ""; int yuanIndex = str.indexOf("元"); if (yuanIndex >= 0) { integerPartStr = str.substring(0, yuanIndex); String rest = str.substring(yuanIndex + 1); int jiaoIndex = rest.indexOf("角"); int fenIndex = rest.indexOf("分"); if (jiaoIndex >= 0) { decimalPartStr += chineseDigitToNumber(rest.substring(0, jiaoIndex)) + ""; } else if (fenIndex > 0) { decimalPartStr += "0"; } if (fenIndex >= 0) { String fenStr = rest.substring(jiaoIndex >= 0 ? jiaoIndex + 1 : 0, fenIndex); decimalPartStr += chineseDigitToNumber(fenStr) + ""; } else { if (decimalPartStr.length() == 1) { decimalPartStr += "0"; } } } else { // 没有“元”,按纯数字中文处理 integerPartStr = str; } long integerPart = chineseIntegerToNumber(integerPartStr); if (decimalPartStr.isEmpty()) { decimalPartStr = "00"; } else if (decimalPartStr.length() == 1) { decimalPartStr += "0"; } BigDecimal result = new BigDecimal(integerPart + "." + decimalPartStr); return negative ? result.negate() : result; } /** * 中文整数转 long */ private static long chineseIntegerToNumber(String chinese) { if (chinese == null || chinese.isEmpty() || chinese.equals("零")) { return 0; } long result = 0; long section = 0; long number = 0; for (int i = 0; i < chinese.length(); i++) { char c = chinese.charAt(i); if (CN_NUM_MAP.containsKey(c)) { number = CN_NUM_MAP.get(c); } else if (CN_UNIT_MAP.containsKey(c)) { int unit = CN_UNIT_MAP.get(c); if (number == 0) { number = 1; } section += number * unit; number = 0; } else if (c == '万') { section += number; result += section * 10000; section = 0; number = 0; } else if (c == '亿') { section += number; result += section * 100000000; section = 0; number = 0; } else if (c == '兆') { section += number; result += section * 1000000000000L; section = 0; number = 0; } } return result + section + number; } private static int chineseDigitToNumber(String chinese) { if (chinese == null || chinese.isEmpty()) { return 0; } char c = chinese.charAt(0); return CN_NUM_MAP.getOrDefault(c, 0); } }