Compare commits

...

3 Commits

6 changed files with 178 additions and 39 deletions

View File

@ -16,7 +16,6 @@
package cn.hutool.v7.core.codec.binary;
import cn.hutool.v7.core.text.CharUtil;
import cn.hutool.v7.core.text.StrUtil;
import java.awt.Color;
@ -249,16 +248,42 @@ public class HexUtil extends Hex {
* @param prefix 自定义前缀如0x
* @return 格式化后的字符串
*/
public static String format(final String hexStr, String prefix) {
public static String format(final String hexStr, final String prefix) {
return format(hexStr, prefix, StrUtil.SPACE);
}
/**
* 格式化Hex字符串结果为每2位加一个空格类似于
* <pre>
* e8 8c 67 03 80 cb 22 00 95 26 8f
* </pre>
*
* @param hexStr Hex字符串
* @param prefix 自定义前缀如0x
* @param separator 自定义分隔符如空格
* @return 格式化后的字符串
*/
public static String format(final String hexStr, String prefix, String separator) {
if (StrUtil.isEmpty(hexStr)) {
return StrUtil.EMPTY;
}
if (null == prefix) {
prefix = StrUtil.EMPTY;
}
if (null == separator) {
separator = StrUtil.SPACE;
}
final int length = hexStr.length();
final StringBuilder builder = StrUtil.builder(length + length / 2 + (length / 2 * prefix.length()));
builder.append(prefix).append(hexStr.charAt(0)).append(hexStr.charAt(1));
for (int i = 2; i < length - 1; i += 2) {
builder.append(CharUtil.SPACE).append(prefix).append(hexStr.charAt(i)).append(hexStr.charAt(i + 1));
for (int i = 0; i < length; i++) {
if (i % 2 == 0) {
if (i != 0) {
builder.append(separator);
}
builder.append(prefix);
}
builder.append(hexStr.charAt(i));
}
return builder.toString();
}

View File

@ -89,29 +89,28 @@ public class SplitIter extends ComputeIter<String> implements Serializable {
return text.substring(offset);
}
final int start = finder.start(offset);
// 无分隔符结束
if (start < 0) {
// 如果不再有分隔符但是遗留了字符则单独作为一个段
if (offset <= text.length()) {
final String result = text.substring(offset);
if (!ignoreEmpty || !result.isEmpty()) {
// 返回非空串
offset = Integer.MAX_VALUE;
return result;
String result;
int start;
do {
start = finder.start(offset);
// 无分隔符结束
if (start < 0) {
// 如果不再有分隔符但是遗留了字符则单独作为一个段
if (offset <= text.length()) {
result = text.substring(offset);
if (!ignoreEmpty || !result.isEmpty()) {
// 返回非空串
offset = Integer.MAX_VALUE;
return result;
}
}
return null;
}
return null;
}
// 找到新的分隔符位置
final String result = text.substring(offset, start);
offset = finder.end(start);
if (ignoreEmpty && result.isEmpty()) {
// 发现空串且需要忽略时跳过之
return computeNext();
}
// 找到新的分隔符位置
result = text.substring(offset, start);
offset = finder.end(start);
} while (ignoreEmpty && result.isEmpty()); // 空串则继续循环
count++;
return result;

View File

@ -23,9 +23,12 @@ import cn.hutool.v7.core.text.finder.StrFinder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class SplitIterTest {
@Test
@ -38,7 +41,7 @@ public class SplitIterTest {
Integer.MAX_VALUE,
false
);
Assertions.assertEquals(6, splitIter.toList(false).size());
assertEquals(6, splitIter.toList(false).size());
}
@Test
@ -51,7 +54,7 @@ public class SplitIterTest {
Integer.MAX_VALUE,
false
);
Assertions.assertEquals(4, splitIter.toList(false).size());
assertEquals(4, splitIter.toList(false).size());
}
@Test
@ -65,7 +68,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(4, strings.size());
assertEquals(4, strings.size());
}
@Test
@ -79,10 +82,10 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(true);
Assertions.assertEquals(3, strings.size());
Assertions.assertEquals("a", strings.get(0));
Assertions.assertEquals("efedsfs", strings.get(1));
Assertions.assertEquals("ddf", strings.get(2));
assertEquals(3, strings.size());
assertEquals("a", strings.get(0));
assertEquals("efedsfs", strings.get(1));
assertEquals("ddf", strings.get(2));
}
@Test
@ -96,7 +99,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(3, strings.size());
assertEquals(3, strings.size());
}
@Test
@ -110,7 +113,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(3, strings.size());
assertEquals(3, strings.size());
}
@Test
@ -123,7 +126,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(4, strings.size());
assertEquals(4, strings.size());
}
@Test
@ -136,7 +139,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(3, strings.size());
assertEquals(3, strings.size());
}
@Test
@ -149,7 +152,7 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(1, strings.size());
assertEquals(1, strings.size());
}
// 切割字符串是空字符串时报错
@ -164,7 +167,21 @@ public class SplitIterTest {
);
final List<String> strings = splitIter.toList(false);
Assertions.assertEquals(1, strings.size());
assertEquals(1, strings.size());
});
}
@Test
public void issue4169Test() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 20000; i++) { // 1万次连续分隔符模拟递归深度风险场景
sb.append(",");
}
sb.append("test");
final SplitIter iter = new SplitIter(sb.toString(), new StrFinder(",",false), 0, true);
final List<String> result = iter.toList(false);
assertEquals(Collections.singletonList("test"), result);
}
}

View File

@ -135,4 +135,34 @@ public class HexUtilTest {
final String hex3 = "#FF";
assertEquals(new BigInteger("FF", 16), HexUtil.toBigInteger(hex3));
}
@Test
public void testFormatEmpty() {
final String result = HexUtil.format("");
assertEquals("", result);
}
@Test
public void testFormatSingleChar() {
final String result = HexUtil.format("1");
assertEquals("1", result);
}
@Test
public void testFormatOddLength() {
final String result = HexUtil.format("123");
assertEquals("12 3", result);
}
@Test
public void testFormatWithPrefixSingleChar() {
final String result = HexUtil.format("1", "0x");
assertEquals("0x1", result);
}
@Test
public void testFormatWithPrefixOddLength() {
final String result = HexUtil.format("123", "0x");
assertEquals("0x12 0x3", result);
}
}

View File

@ -119,7 +119,7 @@ public final class CsvParser extends ComputeIter<CsvRow> implements Closeable, S
/**
* 读取下一行数据
*
* @return CsvRow{@code null}表示
* @return CsvRow{@code null}表示读取结束
* @throws IORuntimeException IO读取异常
*/
public CsvRow nextRow() throws IORuntimeException {

View File

@ -0,0 +1,68 @@
package cn.hutool.v7.poi.excel.writer;
import cn.hutool.v7.poi.excel.ExcelUtil;
import cn.hutool.v7.poi.excel.style.StyleUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
public class Issue4146Test {
@Test
@Disabled
public void writeSheetWithStyleTest() {
final ExcelWriter writer = ExcelUtil.getWriter("d:\\test\\issue4146.xlsx", "表格1");
final List<TestUser> list = new ArrayList<>();
TestUser test = new TestUser("张三", 18, 90.0, 0.9878);
list.add(test);
test = new TestUser("李四", 18, 79.5, 0.8311);
list.add(test);
test = new TestUser("王五", 18, 89.9, 0.6932);
list.add(test);
test = new TestUser("赵六", 18, 69.9, 0.7912);
list.add(test);
test = new TestUser("孙七", 18, 79.9, 0.6432);
list.add(test);
final ExcelWriteConfig config = writer.getConfig();
config.addHeaderAlias("name", "姓名");
config.addHeaderAlias("age", "年龄");
config.addHeaderAlias("score", "分数");
config.addHeaderAlias("zb", "占比");
config.setOnlyAlias(true);
writer.write(list, true);
// 百分比的单元格样式必须单独创建使用StyleSet中的样式修改则会修改全局样式
final CellStyle percentCellStyle = writer.createCellStyle();
percentCellStyle.setDataFormat(writer.getWorkbook().createDataFormat().getFormat("0.00%"));
// 填充背景颜色必须指定FillPatternType才有效
StyleUtil.setColor(percentCellStyle, IndexedColors.YELLOW, FillPatternType.SOLID_FOREGROUND);
// 设置边框颜色和粗细
StyleUtil.setBorder(percentCellStyle, BorderStyle.THIN, IndexedColors.BLACK);
final int rowCount = writer.getRowCount();
// 设置列样式无效除非将默认样式清除因此必须在写出数据后为单元格指定自定义的样式
for (int i = 1; i < rowCount; i++) {
writer.setStyle(percentCellStyle, 3, i);
}
writer.close();
}
@Data
@AllArgsConstructor
static class TestUser {
private String name;
private Integer age;
private Double score;
private Double zb;
}
}