mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add read bean for csv
This commit is contained in:
parent
9440512d54
commit
6b3be8468c
@ -8,6 +8,7 @@
|
||||
### 新特性
|
||||
* 【core 】 NumberConverter Long类型增加日期转换(pr#872@Github)
|
||||
* 【all 】 StrUtil and SymmetricCrypto注释修正(pr#873@Github)
|
||||
* 【core 】 CsvReader支持返回Bean(issue#869@Github)
|
||||
|
||||
### Bug修复
|
||||
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.EnumerationIter;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.ClassLoaderUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
@ -61,41 +62,52 @@ public class ResourceUtil {
|
||||
/**
|
||||
* 从ClassPath资源中获取{@link InputStream}
|
||||
*
|
||||
* @param resurce ClassPath资源
|
||||
* @param resource ClassPath资源
|
||||
* @return {@link InputStream}
|
||||
* @throws NoResourceException 资源不存在异常
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static InputStream getStream(String resurce) throws NoResourceException {
|
||||
return getResourceObj(resurce).getStream();
|
||||
public static InputStream getStream(String resource) throws NoResourceException {
|
||||
return getResourceObj(resource).getStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ClassPath资源中获取{@link InputStream},当资源不存在时返回null
|
||||
*
|
||||
* @param resurce ClassPath资源
|
||||
* @param resource ClassPath资源
|
||||
* @return {@link InputStream}
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static InputStream getStreamSafe(String resurce) {
|
||||
public static InputStream getStreamSafe(String resource) {
|
||||
try {
|
||||
return getResourceObj(resurce).getStream();
|
||||
return getResourceObj(resource).getStream();
|
||||
} catch (NoResourceException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ClassPath资源中获取{@link BufferedReader}
|
||||
*
|
||||
* @param resource ClassPath资源
|
||||
* @return {@link InputStream}
|
||||
* @since 5.3.6
|
||||
*/
|
||||
public static BufferedReader getUtf8Reader(String resource) {
|
||||
return getReader(resource, CharsetUtil.CHARSET_UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ClassPath资源中获取{@link BufferedReader}
|
||||
*
|
||||
* @param resurce ClassPath资源
|
||||
* @param resource ClassPath资源
|
||||
* @param charset 编码
|
||||
* @return {@link InputStream}
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static BufferedReader getReader(String resurce, Charset charset) {
|
||||
return getResourceObj(resurce).getReader(charset);
|
||||
public static BufferedReader getReader(String resource, Charset charset) {
|
||||
return getResourceObj(resource).getReader(charset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -143,17 +144,6 @@ public class CsvBaseReader implements Serializable {
|
||||
return read(FileUtil.getReader(path, charset));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Reader中读取CSV数据,读取后关闭Reader
|
||||
*
|
||||
* @param reader Reader
|
||||
* @param rowHandler 行处理器,用于一行一行的处理数据
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public void read(Reader reader, CsvRowHandler rowHandler) throws IORuntimeException {
|
||||
read(parse(reader), rowHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Reader中读取CSV数据,读取后关闭Reader
|
||||
*
|
||||
@ -170,6 +160,52 @@ public class CsvBaseReader implements Serializable {
|
||||
return new CsvData(header, rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Reader中读取CSV数据,结果为Map,读取后关闭Reader。<br>
|
||||
* 此方法默认识别首行为标题行。
|
||||
*
|
||||
* @param reader Reader
|
||||
* @return {@link CsvData},包含数据列表和行信息
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public List<Map<String, String>> readMapList(Reader reader) throws IORuntimeException {
|
||||
// 此方法必须包含标题
|
||||
this.config.setContainsHeader(true);
|
||||
|
||||
final List<Map<String, String>> result = new ArrayList<>();
|
||||
read(reader, (row) -> result.add(row.getFieldMap()));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Reader中读取CSV数据并转换为Bean列表,读取后关闭Reader。<br>
|
||||
* 此方法默认识别首行为标题行。
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param reader Reader
|
||||
* @param clazz Bean类型
|
||||
* @return Bean列表
|
||||
*/
|
||||
public <T> List<T> read(Reader reader, Class<T> clazz) {
|
||||
// 此方法必须包含标题
|
||||
this.config.setContainsHeader(true);
|
||||
|
||||
final List<T> result = new ArrayList<>();
|
||||
read(reader, (row) -> result.add(row.toBean(clazz)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Reader中读取CSV数据,读取后关闭Reader
|
||||
*
|
||||
* @param reader Reader
|
||||
* @param rowHandler 行处理器,用于一行一行的处理数据
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public void read(Reader reader, CsvRowHandler rowHandler) throws IORuntimeException {
|
||||
read(parse(reader), rowHandler);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.hutool.core.text.csv;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -74,7 +76,7 @@ public final class CsvRow implements List<String> {
|
||||
/**
|
||||
* 获取标题与字段值对应的Map
|
||||
*
|
||||
* @return an unmodifiable map of header names and field values of this row
|
||||
* @return 标题与字段值对应的Map
|
||||
* @throws IllegalStateException CSV文件无标题行抛出此异常
|
||||
*/
|
||||
public Map<String, String> getFieldMap() {
|
||||
@ -82,7 +84,7 @@ public final class CsvRow implements List<String> {
|
||||
throw new IllegalStateException("No header available");
|
||||
}
|
||||
|
||||
final Map<String, String> fieldMap = new LinkedHashMap<>(headerMap.size());
|
||||
final Map<String, String> fieldMap = new LinkedHashMap<>(headerMap.size(), 1);
|
||||
String key;
|
||||
Integer col;
|
||||
String val;
|
||||
@ -96,6 +98,18 @@ public final class CsvRow implements List<String> {
|
||||
return fieldMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 一行数据转换为Bean对象
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param clazz bean类
|
||||
* @return Bean
|
||||
* @since 5.3.6
|
||||
*/
|
||||
public <T> T toBean(Class<T> clazz){
|
||||
return BeanUtil.mapToBean(getFieldMap(), clazz, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段格式
|
||||
*
|
||||
|
@ -1,10 +1,14 @@
|
||||
package cn.hutool.core.text.csv;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import lombok.Data;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CsvReaderTest {
|
||||
|
||||
@ -14,4 +18,57 @@ public class CsvReaderTest {
|
||||
CsvData data = reader.read(ResourceUtil.getReader("test.csv", CharsetUtil.CHARSET_UTF_8));
|
||||
Assert.assertEquals("关注\"对象\"", data.getRow(0).get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readMapListTest(){
|
||||
final CsvReader reader = CsvUtil.getReader();
|
||||
final List<Map<String, String>> result = reader.readMapList(
|
||||
ResourceUtil.getUtf8Reader("test_bean.csv"));
|
||||
|
||||
Assert.assertEquals("张三", result.get(0).get("姓名"));
|
||||
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("姓名"));
|
||||
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("姓名"));
|
||||
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();
|
||||
final List<TestBean> result = reader.read(
|
||||
ResourceUtil.getUtf8Reader("test_bean.csv"), TestBean.class);
|
||||
|
||||
Assert.assertEquals("张三", result.get(0).getName());
|
||||
Assert.assertEquals("男", result.get(0).getGender());
|
||||
Assert.assertEquals("无", result.get(0).getFocus());
|
||||
Assert.assertEquals(Integer.valueOf(33), result.get(0).getAge());
|
||||
|
||||
Assert.assertEquals("李四", result.get(1).getName());
|
||||
Assert.assertEquals("男", result.get(1).getGender());
|
||||
Assert.assertEquals("好对象", result.get(1).getFocus());
|
||||
Assert.assertEquals(Integer.valueOf(23), result.get(1).getAge());
|
||||
|
||||
Assert.assertEquals("王妹妹", result.get(2).getName());
|
||||
Assert.assertEquals("女", result.get(2).getGender());
|
||||
Assert.assertEquals("特别关注", result.get(2).getFocus());
|
||||
Assert.assertEquals(Integer.valueOf(22), result.get(2).getAge());
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class TestBean{
|
||||
@Alias("姓名")
|
||||
private String name;
|
||||
private String gender;
|
||||
private String focus;
|
||||
private Integer age;
|
||||
}
|
||||
}
|
||||
|
4
hutool-core/src/test/resources/test_bean.csv
Normal file
4
hutool-core/src/test/resources/test_bean.csv
Normal file
@ -0,0 +1,4 @@
|
||||
姓名,gender,focus,age
|
||||
张三,男,无,33
|
||||
李四,男,好对象,23
|
||||
王妹妹,女,特别关注,22
|
|
Loading…
x
Reference in New Issue
Block a user