From b8d04654efd0f4051d4452f0fd5701eed8097bfe Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 10 Jul 2021 00:36:13 +0800 Subject: [PATCH] fix chineseFormatter --- .../core/convert/NumberChineseFormatter.java | 24 ++++++++++++------- .../cn/hutool/core/text/CharSequenceUtil.java | 20 +++++++++++++--- .../cn/hutool/core/text/csv/CsvParser.java | 4 ++++ .../convert/NumberChineseFormatterTest.java | 18 +++++++++----- hutool-core/src/test/resources/test.csv | 0 5 files changed, 49 insertions(+), 17 deletions(-) mode change 100644 => 100755 hutool-core/src/test/resources/test.csv diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java index 8a92735be..ad519a68e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/NumberChineseFormatter.java @@ -59,7 +59,7 @@ public class NumberChineseFormatter { * @return 中文 */ public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) { - if (amount > 99999999999999.99 || amount < -99999999999999.99) { + if (amount > 99_9999_9999_9999.99 || amount < -99999999999999.99) { throw new IllegalArgumentException("Number support only: (-99999999999999.99 ~ 99999999999999.99)!"); } @@ -77,33 +77,41 @@ public class NumberChineseFormatter { //将数字以万为单位分为多份 int[] parts = new int[20]; - int numParts = 0; + int partsCount = 0; for (int i = 0; temp != 0; i++) { int part = (int) (temp % 10000); parts[i] = part; - numParts++; + partsCount++; temp = temp / 10000; } - boolean beforeWanIsZero = true; // 标志“万”下面一级是不是 0 + boolean underWanIsZero = true; // 标志“万”下面一级是不是 0 StringBuilder chineseStr = new StringBuilder(); - for (int i = 0; i < numParts; i++) { + for (int i = 0; i < partsCount; i++) { final String partChinese = toChinese(parts[i], isUseTraditional); if (i % 2 == 0) { - beforeWanIsZero = StrUtil.isEmpty(partChinese); + underWanIsZero = StrUtil.isEmpty(partChinese); } + // TODO 此处逻辑过于复杂,等待整理重构 if (i != 0) { if (i % 2 == 0) { + if (parts[i - 1] < 1000) { + // 如果"亿"的部分不为 0, 而"亿"以下的部分小于 1000,则亿后面应该跟“零”,如一亿零三十五万 + chineseStr.insert(0, "零"); + } chineseStr.insert(0, "亿"); } else { - if ("".equals(partChinese) && false == beforeWanIsZero) { + if (StrUtil.isEmpty(partChinese) && false == underWanIsZero) { // 如果“万”对应的 part 为 0,而“万”下面一级不为 0,则不加“万”,而加“零” chineseStr.insert(0, "零"); } else { if (parts[i - 1] < 1000 && parts[i - 1] > 0) { - // 如果"万"的部分不为 0, 而"万"前面的部分小于 1000 大于 0, 则万后面应该跟“零” + // 如果"万"的部分不为 0, 而"万"以下的部分小于 1000 大于 0, 则万后面应该跟“零”,如一万零三百 + chineseStr.insert(0, "零"); + } else if(parts[i] > 0 && parts[i] % 10 == 0){ + // 如果万的部分没有个位数,需跟“零”,如十万零八千 chineseStr.insert(0, "零"); } if (parts[i] > 0) { diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index d2eb3bc04..a86d1ef6e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.function.Predicate; /** * {@link CharSequence} 相关工具类封装 @@ -617,6 +618,19 @@ public class CharSequenceUtil { * @return 除去指定字符后的的字符串,如果原字串为{@code null},则返回{@code null} */ public static String trim(CharSequence str, int mode) { + return trim(str, mode, CharUtil::isBlankChar); + } + + /** + * 按照断言,除去字符串头尾部的断言为真的字符,如果字符串是{@code null},依然返回{@code null}。 + * + * @param str 要处理的字符串 + * @param mode {@code -1}表示trimStart,{@code 0}表示trim全部, {@code 1}表示trimEnd + * @param predicate 断言是否过掉字符,返回{@code true}表述过滤掉,{@code false}表示不过滤 + * @return 除去指定字符后的的字符串,如果原字串为{@code null},则返回{@code null} + * @since 5.7.4 + */ + public static String trim(CharSequence str, int mode, Predicate predicate) { String result; if (str == null) { result = null; @@ -625,12 +639,12 @@ public class CharSequenceUtil { int start = 0; int end = length;// 扫描字符串头部 if (mode <= 0) { - while ((start < end) && (CharUtil.isBlankChar(str.charAt(start)))) { + while ((start < end) && (predicate.test(str.charAt(start)))) { start++; } }// 扫描字符串尾部 if (mode >= 0) { - while ((start < end) && (CharUtil.isBlankChar(str.charAt(end - 1)))) { + while ((start < end) && (predicate.test(str.charAt(end - 1)))) { end--; } } @@ -3878,7 +3892,7 @@ public class CharSequenceUtil { * 过滤字符串 * * @param str 字符串 - * @param filter 过滤器 + * @param filter 过滤器,{@link Filter#accept(Object)}返回为{@code true}的保留字符 * @return 过滤后的字符串 * @since 5.4.0 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java index c6d0bae2f..43437874c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvParser.java @@ -324,6 +324,10 @@ public final class CsvParser implements Closeable, Serializable { */ private void addField(List currentFields, String field) { final char textDelimiter = this.config.textDelimiter; + + // 忽略多余引号后的换行符 + field = StrUtil.trim(field, 1, (c-> c == CharUtil.LF || c == CharUtil.CR)); + field = StrUtil.unWrap(field, textDelimiter); field = StrUtil.replace(field, "" + textDelimiter + textDelimiter, textDelimiter + ""); currentFields.add(field); diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java index 72f72b1fd..3fce2769c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java @@ -16,7 +16,7 @@ public class NumberChineseFormatterTest { f1 = NumberChineseFormatter.format(1024, false); Assert.assertEquals("一千零二十四", f1); f1 = NumberChineseFormatter.format(100350089, false); - Assert.assertEquals("一亿三十五万零八十九", f1); + Assert.assertEquals("一亿零三十五万零八十九", f1); f1 = NumberChineseFormatter.format(1200, false); Assert.assertEquals("一千二百", f1); f1 = NumberChineseFormatter.format(12, false); @@ -36,11 +36,17 @@ public class NumberChineseFormatterTest { @Test public void formatTest3() { - String f1 = NumberChineseFormatter.format(50008000, false, false); - Assert.assertEquals("五千万零八千", f1); +// String f1 = NumberChineseFormatter.format(5000_8000, false, false); +// Assert.assertEquals("五千万零八千", f1); - f1 = NumberChineseFormatter.format(100350089, false, false); - Assert.assertEquals("一亿零三十五万零八十九\"", f1); + String f2 = NumberChineseFormatter.format(1_0035_0089, false, false); + Assert.assertEquals("一亿零三十五万零八十九", f2); + } + + @Test + public void formatMaxTest() { + String f3 = NumberChineseFormatter.format(99_9999_9999_9999L, false, false); + Assert.assertEquals("九十九万九千九百九十九亿九千九百九十九万九千九百九十九", f3); } @Test @@ -54,7 +60,7 @@ public class NumberChineseFormatterTest { f1 = NumberChineseFormatter.format(1024, true); Assert.assertEquals("壹仟零贰拾肆", f1); f1 = NumberChineseFormatter.format(100350089, true); - Assert.assertEquals("壹亿叁拾伍万零捌拾玖", f1); + Assert.assertEquals("壹亿零叁拾伍万零捌拾玖", f1); f1 = NumberChineseFormatter.format(1200, true); Assert.assertEquals("壹仟贰佰", f1); f1 = NumberChineseFormatter.format(12, true); diff --git a/hutool-core/src/test/resources/test.csv b/hutool-core/src/test/resources/test.csv old mode 100644 new mode 100755