mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
ec204f8fc2
commit
5a4fbd4386
@ -12,6 +12,8 @@
|
||||
|
||||
package org.dromara.hutool.core.math;
|
||||
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.core.text.CharUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
@ -123,6 +125,73 @@ public class NumberParser {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换char数组为一个int值,此方法拷贝自{@link Integer#parseInt(String, int)}<br>
|
||||
* 拷贝的原因是直接转换char[]避免创建String对象造成的多余拷贝<br>
|
||||
* 此方法自动跳过首尾空白符
|
||||
*
|
||||
* @param chars char数组
|
||||
* @param radix 进制数
|
||||
* @return int值
|
||||
* @see Integer#parseInt(String, int)
|
||||
*/
|
||||
public int parseInt(final char[] chars, final int radix) {
|
||||
if (ArrayUtil.isEmpty(chars)) {
|
||||
throw new IllegalArgumentException("Empty chars!");
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
boolean negative = false;
|
||||
int i = 0;
|
||||
int limit = -Integer.MAX_VALUE;
|
||||
int digit;
|
||||
|
||||
// 跳过空白符
|
||||
while (CharUtil.isBlankChar(chars[i])) {
|
||||
i++;
|
||||
}
|
||||
|
||||
final char firstChar = chars[i];
|
||||
if (firstChar < '0') { // Possible leading "+" or "-"
|
||||
if (firstChar == '-') {
|
||||
negative = true;
|
||||
limit = Integer.MIN_VALUE;
|
||||
} else if (firstChar != '+') {
|
||||
throw new NumberFormatException("Invalid first char: " + firstChar);
|
||||
}
|
||||
|
||||
if (chars.length == 1) {
|
||||
// Cannot have lone "+" or "-"
|
||||
throw new NumberFormatException("Invalid chars has lone: " + firstChar);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
final int multmin = limit / radix;
|
||||
while (i < chars.length) {
|
||||
// 跳过空白符
|
||||
if (CharUtil.isBlankChar(chars[i])) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Accumulating negatively avoids surprises near MAX_VALUE
|
||||
digit = Character.digit(chars[i++], radix);
|
||||
if (digit < 0) {
|
||||
throw new NumberFormatException(StrUtil.format("Invalid chars: {} at {}", chars, i - 1));
|
||||
}
|
||||
if (result < multmin) {
|
||||
throw new NumberFormatException(StrUtil.format("Invalid chars: {}", new Object[]{chars}));
|
||||
}
|
||||
result *= radix;
|
||||
if (result < limit + digit) {
|
||||
throw new NumberFormatException(StrUtil.format("Invalid chars: {}", new Object[]{chars}));
|
||||
}
|
||||
result -= digit;
|
||||
}
|
||||
return negative ? result : -result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析转换数字字符串为long型数字,规则如下:
|
||||
*
|
||||
@ -293,7 +362,7 @@ public class NumberParser {
|
||||
if (null == locale) {
|
||||
locale = Locale.getDefault(Locale.Category.FORMAT);
|
||||
}
|
||||
if(StrUtil.startWith(numberStr, CharUtil.PLUS)){
|
||||
if (StrUtil.startWith(numberStr, CharUtil.PLUS)) {
|
||||
// issue#I79VS7
|
||||
numberStr = StrUtil.subSuf(numberStr, 1);
|
||||
}
|
||||
|
@ -1230,6 +1230,22 @@ public class NumberUtil extends NumberValidator {
|
||||
return NumberParser.INSTANCE.parseInt(numberStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换char数组为一个int值,此方法拷贝自{@link Integer#parseInt(String, int)}<br>
|
||||
* 拷贝的原因是直接转换char[]避免创建String对象造成的多余拷贝。<br>
|
||||
* 此方法自动跳过首尾空白符
|
||||
*
|
||||
* @param chars char数组
|
||||
* @param radix 进制数
|
||||
* @return int值
|
||||
* @throws NumberFormatException 数字格式异常
|
||||
* @see Integer#parseInt(String, int)
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static int parseInt(final char[] chars, final int radix) throws NumberFormatException {
|
||||
return NumberParser.INSTANCE.parseInt(chars, radix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析转换数字字符串为 {@link java.lang.Long } 规则如下:
|
||||
*
|
||||
|
@ -15,10 +15,51 @@ package org.dromara.hutool.core.math;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class NumberParserTest {
|
||||
@Test
|
||||
void parseLongTest() {
|
||||
final long value = NumberParser.INSTANCE.parseLong("0.a");
|
||||
Assertions.assertEquals(0L, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseIntWithValidInputs() {
|
||||
// Test with various valid inputs
|
||||
assertEquals(123, NumberParser.INSTANCE.parseInt("123".toCharArray(), 10));
|
||||
assertEquals(-123, NumberParser.INSTANCE.parseInt("-123".toCharArray(), 10));
|
||||
assertEquals(123, NumberParser.INSTANCE.parseInt("+123".toCharArray(), 10));
|
||||
assertEquals(0, NumberParser.INSTANCE.parseInt("0".toCharArray(), 10));
|
||||
assertEquals(255, NumberParser.INSTANCE.parseInt("ff".toCharArray(), 16));
|
||||
assertEquals(-255, NumberParser.INSTANCE.parseInt("-ff".toCharArray(), 16));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseIntWithInvalidInputs() {
|
||||
// Test with various invalid inputs
|
||||
assertThrows(IllegalArgumentException.class, () -> NumberParser.INSTANCE.parseInt("".toCharArray(), 10));
|
||||
assertThrows(NumberFormatException.class, () -> NumberParser.INSTANCE.parseInt("1234".toCharArray(), 2));
|
||||
assertThrows(NumberFormatException.class, () -> NumberParser.INSTANCE.parseInt("abc".toCharArray(), 10));
|
||||
assertThrows(NumberFormatException.class, () -> NumberParser.INSTANCE.parseInt("--123".toCharArray(), 10));
|
||||
assertThrows(NumberFormatException.class, () -> NumberParser.INSTANCE.parseInt("++123".toCharArray(), 10));
|
||||
assertThrows(NumberFormatException.class, () -> NumberParser.INSTANCE.parseInt("123".toCharArray(), 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseIntWithLeadingAndTrailingWhitespace() {
|
||||
// Test with leading and trailing whitespace
|
||||
assertEquals(42, NumberParser.INSTANCE.parseInt(" 42 ".toCharArray(), 10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseIntWithMaxAndMinInt() {
|
||||
// Test with values at the edge of int range
|
||||
final char[] maxIntStr = Integer.toString(Integer.MAX_VALUE).toCharArray();
|
||||
final char[] minIntStr = Integer.toString(Integer.MIN_VALUE).toCharArray();
|
||||
|
||||
assertEquals(Integer.MAX_VALUE, NumberParser.INSTANCE.parseInt(maxIntStr, 10));
|
||||
assertEquals(Integer.MIN_VALUE, NumberParser.INSTANCE.parseInt(minIntStr, 10));
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* {@link NumberUtil} 单元测试类
|
||||
@ -320,7 +321,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void decimalFormatNaNTest() {
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
assertThrows(IllegalArgumentException.class, ()->{
|
||||
final Double a = 0D;
|
||||
final Double b = 0D;
|
||||
|
||||
@ -331,7 +332,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void decimalFormatNaNTest2() {
|
||||
Assertions.assertThrows(IllegalArgumentException.class, ()->{
|
||||
assertThrows(IllegalArgumentException.class, ()->{
|
||||
final Double a = 0D;
|
||||
final Double b = 0D;
|
||||
|
||||
@ -383,7 +384,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
void emptyToBigDecimalTest(){
|
||||
Assertions.assertThrows(IllegalArgumentException.class,()->{
|
||||
assertThrows(IllegalArgumentException.class,()->{
|
||||
NumberUtil.toBigDecimal("");
|
||||
});
|
||||
}
|
||||
@ -445,7 +446,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void parseIntTest3() {
|
||||
Assertions.assertThrows(NumberFormatException.class, ()->{
|
||||
assertThrows(NumberFormatException.class, ()->{
|
||||
final int v1 = NumberUtil.parseInt("d");
|
||||
assertEquals(0, v1);
|
||||
});
|
||||
@ -453,7 +454,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void parseIntTest4() {
|
||||
Assertions.assertThrows(NumberFormatException.class, ()->{
|
||||
assertThrows(NumberFormatException.class, ()->{
|
||||
// issue#I5M55F
|
||||
// 科学计数法忽略支持,科学计数法一般用于表示非常小和非常大的数字,这类数字转换为int后精度丢失,没有意义。
|
||||
final String numberStr = "429900013E20220812163344551";
|
||||
@ -692,7 +693,7 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void rangeMinTest() {
|
||||
Assertions.assertThrows(NegativeArraySizeException.class, ()->{
|
||||
assertThrows(NegativeArraySizeException.class, ()->{
|
||||
NumberUtil.range(0, Integer.MIN_VALUE);
|
||||
});
|
||||
}
|
||||
@ -757,7 +758,7 @@ public class NumberUtilTest {
|
||||
@EnabledForJreRange(max = JRE.JAVA_8)
|
||||
void numberFormatTest() {
|
||||
// JDK8下,NaN解析报错,JDK9+中返回0
|
||||
Assertions.assertThrows(ParseException.class, ()->{
|
||||
assertThrows(ParseException.class, ()->{
|
||||
NumberFormat.getInstance().parse("NaN");
|
||||
});
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.json;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.io.ReaderWrapper;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.math.NumberUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -171,27 +172,21 @@ public class JSONTokener extends ReaderWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last character read from the input or '\0' if nothing has been read yet.
|
||||
* 获取上一个读取的字符,如果没有读取过则返回'\0'
|
||||
*
|
||||
* @return the last character read from the input.
|
||||
* @return 上一个读取的字符
|
||||
*/
|
||||
protected char getPrevious() {
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取下一个字符,并比对是否和指定字符匹配
|
||||
*
|
||||
* @param c 被匹配的字符
|
||||
* @return The character 匹配到的字符
|
||||
* @throws JSONException 如果不匹配抛出此异常
|
||||
* 获取16进制unicode转义符对应的字符值,如:
|
||||
* <pre>{@code '4f60' -> '你'}</pre>
|
||||
* @return 字符
|
||||
*/
|
||||
public char next(final char c) throws JSONException {
|
||||
final char n = this.next();
|
||||
if (n != c) {
|
||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" + n + "'");
|
||||
}
|
||||
return n;
|
||||
public char nextUnicode(){
|
||||
return (char) NumberUtil.parseInt(next(4), 16);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,12 +196,9 @@ public class JSONTokener extends ReaderWrapper {
|
||||
* @return 获得的n个字符组成的字符串
|
||||
* @throws JSONException 如果源中余下的字符数不足以提供所需的字符数,抛出此异常
|
||||
*/
|
||||
public String next(final int n) throws JSONException {
|
||||
if (n == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public char[] next(final int n) throws JSONException {
|
||||
final char[] chars = new char[n];
|
||||
|
||||
int pos = 0;
|
||||
while (pos < n) {
|
||||
chars[pos] = this.next();
|
||||
@ -215,7 +207,7 @@ public class JSONTokener extends ReaderWrapper {
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
return new String(chars);
|
||||
return chars;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -276,7 +268,7 @@ public class JSONTokener extends ReaderWrapper {
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'u':// Unicode符
|
||||
sb.append((char) Integer.parseInt(this.next(4), 16));
|
||||
sb.append(nextUnicode());
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
|
Loading…
x
Reference in New Issue
Block a user