Skip to content

Commit

Permalink
add alias support
Browse files Browse the repository at this point in the history
  • Loading branch information
looly committed Aug 26, 2021
1 parent b1b8a29 commit e800b9c
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* 【core 】 增加PartitionIter(pr#402@Gitee)
* 【all 】 增加异常爬栈开关(pr#403@Gitee)
* 【core 】 优化Combination中C(n,n)的逻辑(pr#1792@Github)
* 【core 】 Csv读写支持别名(issue#1791@Github)

### 🐞Bug修复
* 【core 】 修复MapUtil.sort比较器不一致返回原map的问题(issue#I46AQJ@Gitee)
Expand Down
47 changes: 44 additions & 3 deletions hutool-core/src/main/java/cn/hutool/core/text/csv/CsvConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import cn.hutool.core.util.CharUtil;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* CSV基础配置项,此配置项可用于读取和写出CSV,定义了包括字段分隔符、文本包装符等符号
Expand All @@ -11,6 +13,7 @@
* @author looly
* @since 4.0.5
*/
@SuppressWarnings("unchecked")
public class CsvConfig<T extends CsvConfig<T>> implements Serializable {
private static final long serialVersionUID = -8069578249066158459L;

Expand All @@ -26,14 +29,17 @@ public class CsvConfig<T extends CsvConfig<T>> implements Serializable {
* 注释符号,用于区分注释行,默认'#'
*/
protected char commentCharacter = '#';
/**
* 标题别名
*/
protected Map<String, String> headerAlias = new LinkedHashMap<>();

/**
* 设置字段分隔符,默认逗号','
*
* @param fieldSeparator 字段分隔符,默认逗号','
* @return this
*/
@SuppressWarnings("unchecked")
public T setFieldSeparator(final char fieldSeparator) {
this.fieldSeparator = fieldSeparator;
return (T) this;
Expand All @@ -45,7 +51,6 @@ public T setFieldSeparator(final char fieldSeparator) {
* @param textDelimiter 文本分隔符,文本包装符,默认双引号'"'
* @return this
*/
@SuppressWarnings("unchecked")
public T setTextDelimiter(char textDelimiter) {
this.textDelimiter = textDelimiter;
return (T) this;
Expand All @@ -58,9 +63,45 @@ public T setTextDelimiter(char textDelimiter) {
* @return this
* @since 5.5.7
*/
@SuppressWarnings("unchecked")
public T setCommentCharacter(char commentCharacter) {
this.commentCharacter = commentCharacter;
return (T) this;
}

/**
* 设置标题行的别名Map
*
* @param headerAlias 别名Map
* @return this
* @since 5.7.10
*/
public T setHeaderAlias(Map<String, String> headerAlias) {
this.headerAlias = headerAlias;
return (T) this;
}

/**
* 增加标题别名
*
* @param header 标题
* @param alias 别名
* @return this
* @since 5.7.10
*/
public T addHeaderAlias(String header, String alias) {
this.headerAlias.put(header, alias);
return (T) this;
}

/**
* 去除标题别名
*
* @param header 标题
* @return this
* @since 5.7.10
*/
public T removeHeaderAlias(String header) {
this.headerAlias.remove(header);
return (T) this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil;
Expand Down Expand Up @@ -165,7 +166,11 @@ public CsvRow nextRow() throws IORuntimeException {
private void initHeader(final List<String> currentFields) {
final Map<String, Integer> localHeaderMap = new LinkedHashMap<>(currentFields.size());
for (int i = 0; i < currentFields.size(); i++) {
final String field = currentFields.get(i);
String field = currentFields.get(i);
if (MapUtil.isNotEmpty(this.config.headerAlias)) {
// 自定义别名
field = ObjectUtil.defaultIfNull(this.config.headerAlias.get(field), field);
}
if (StrUtil.isNotEmpty(field) && false == localHeaderMap.containsKey(field)) {
localHeaderMap.put(field, i);
}
Expand Down
8 changes: 3 additions & 5 deletions hutool-core/src/main/java/cn/hutool/core/text/csv/CsvRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public final class CsvRow implements List<String> {
* @param headerMap 标题Map
* @param fields 数据列表
*/
public CsvRow(final long originalLineNumber, final Map<String, Integer> headerMap, final List<String> fields) {
public CsvRow(long originalLineNumber, Map<String, Integer> headerMap, List<String> fields) {
Assert.notNull(fields, "fields must be not null!");
this.originalLineNumber = originalLineNumber;
this.headerMap = headerMap;
Expand All @@ -53,10 +53,8 @@ public long getOriginalLineNumber() {
* @return 字段值,null表示无此字段值
* @throws IllegalStateException CSV文件无标题行抛出此异常
*/
public String getByName(final String name) {
if (headerMap == null) {
throw new IllegalStateException("No header available");
}
public String getByName(String name) {
Assert.notNull(this.headerMap, "No header available!");

final Integer col = headerMap.get(name);
if (col != null) {
Expand Down
34 changes: 30 additions & 4 deletions hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
Expand All @@ -20,6 +21,7 @@
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -217,8 +219,9 @@ public CsvWriter write(Collection<?> lines) throws IORuntimeException {
public CsvWriter write(CsvData csvData) {
if (csvData != null) {
// 1、写header
if (CollUtil.isNotEmpty(csvData.getHeader())) {
this.writeLine(csvData.getHeader().toArray(new String[0]));
final List<String> header = csvData.getHeader();
if (CollUtil.isNotEmpty(header)) {
this.writeHeaderLine(header.toArray(new String[0]));
}
// 2、写内容
this.write(csvData.getRows());
Expand All @@ -239,8 +242,8 @@ public CsvWriter writeBeans(Collection<?> beans) {
Map<String, Object> map;
for (Object bean : beans) {
map = BeanUtil.beanToMap(bean);
if(isFirst){
writeLine(map.keySet().toArray(new String[0]));
if (isFirst) {
writeHeaderLine(map.keySet().toArray(new String[0]));
isFirst = false;
}
writeLine(Convert.toStrArray(map.values()));
Expand All @@ -250,6 +253,29 @@ public CsvWriter writeBeans(Collection<?> beans) {
return this;
}

/**
* 写出一行头部行,支持标题别名
*
* @param fields 字段列表 ({@code null} 值会被做为空值追加
* @return this
* @throws IORuntimeException IO异常
* @since 5.7.10
*/
public CsvWriter writeHeaderLine(String... fields) throws IORuntimeException {
final Map<String, String> headerAlias = this.config.headerAlias;
if (MapUtil.isNotEmpty(headerAlias)) {
// 标题别名替换
String alias;
for (int i = 0; i < fields.length; i++) {
alias = headerAlias.get(fields[i]);
if (null != alias) {
fields[i] = alias;
}
}
}
return writeLine(fields);
}

/**
* 写出一行
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,31 @@ public void readMapListTest(){
Assert.assertEquals("22", result.get(2).get("age"));
}

@Test
public void readAliasMapListTest(){
final CsvReadConfig csvReadConfig = CsvReadConfig.defaultConfig();
csvReadConfig.addHeaderAlias("姓名", "name");

final CsvReader reader = CsvUtil.getReader(csvReadConfig);
final List<Map<String, String>> result = reader.readMapList(
ResourceUtil.getUtf8Reader("test_bean.csv"));

Assert.assertEquals("张三", result.get(0).get("name"));
Assert.assertEquals("男", result.get(0).get("gender"));
Assert.assertEquals("无", result.get(0).get("focus"));
Assert.assertEquals("33", result.get(0).get("age"));

Assert.assertEquals("李四", result.get(1).get("name"));
Assert.assertEquals("男", result.get(1).get("gender"));
Assert.assertEquals("好对象", result.get(1).get("focus"));
Assert.assertEquals("23", result.get(1).get("age"));

Assert.assertEquals("王妹妹", result.get(2).get("name"));
Assert.assertEquals("女", result.get(2).get("gender"));
Assert.assertEquals("特别关注", result.get(2).get("focus"));
Assert.assertEquals("22", result.get(2).get("age"));
}

@Test
public void readBeanListTest(){
final CsvReader reader = CsvUtil.getReader();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cn.hutool.core.text.csv;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import org.junit.Ignore;
import org.junit.Test;

public class CsvWriterTest {

@Test
@Ignore
public void writeWithAliasTest(){
final CsvWriteConfig csvWriteConfig = CsvWriteConfig.defaultConfig()
.addHeaderAlias("name", "姓名")
.addHeaderAlias("gender", "性别");

final CsvWriter writer = CsvUtil.getWriter(
FileUtil.file("d:/test/csvAliasTest.csv"),
CharsetUtil.CHARSET_GBK, false, csvWriteConfig);

writer.writeHeaderLine("name", "gender", "address");
writer.close();
}
}

0 comments on commit e800b9c

Please sign in to comment.