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<Character, Integer> CN_NUM_MAP = new HashMap<>();
|
private static final Map<Character, Integer> 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);
|
}
|
}
|