配置环境
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>itextpdfartifactId>
<version>5.5.13version>
dependency>
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>itext-asianartifactId>
<version>5.2.0version>
dependency>
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import com.enlistboot.common.exception.ServiceException;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import com.enlistboot.common.annotation.Dbf;
import com.linuxense.javadbf.DBFDataType;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFReader;
import com.linuxense.javadbf.DBFWriter;
public class DBFUtils<E> {
private static final Logger log = LoggerFactory.getLogger(DBFUtils.class);
static Map<String, Object> CONVERTER_EXP_MAP = new HashMap<>(16);
public DBFUtils() {
}
/**
* 导入DBF
*
* @param request
* @param fileParamName
* @throws ServletException
* @throws IOException
*/
public static void importDBF(HttpServletRequest request, String fileParamName)
throws ServletException, IOException {
Part filePart = request.getPart(fileParamName);
String fileName = getFileName(filePart);
// 将文件保存到临时目录
String tempPath = System.getProperty("java.io.tmpdir");
String filePath = tempPath + File.separator + fileName;
saveFile(filePart, filePath);
// 导入DBF数据
// importData(filePath);
// 删除文件
deleteTempFile(tempPath);
}
private static String getFileName(Part part) {
String contentDisposition = part.getHeader("content-disposition");
String[] parts = contentDisposition.split(";");
for (String item : parts) {
if (item.trim().startsWith("filename")) {
return item.substring(item.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
private static void deleteTempFile(String filePath) {
File file = new File(filePath);
if (file.exists()) {
file.delete();
}
}
private static void saveFile(Part part, String filePath) throws IOException {
try (InputStream inputStream = part.getInputStream();
OutputStream outputStream = new FileOutputStream(filePath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
public List<E> importData(InputStream fis, Class<E> cls) throws IOException {
// Charset charset = Charset.forName("GBK");
// Charset charset = Charset.forName("UTF8");
DBFReader reader = new DBFReader(fis, Charset.forName("GBK"));
// 调用DBFReader对实例方法得到path文件中字段的个数
int fieldsCount = reader.getFieldCount();
// 判断是否包含指定的字段
List<Field> classFields = Arrays.asList(cls.getDeclaredFields());
// 取出字段信息
for (int i = 0; i < fieldsCount; i++) {
DBFField field = reader.getField(i);
System.out.println(field.getName());
boolean containsField = classFields.stream()
.anyMatch(f -> f.getName().equals(field.getName()));
if(!containsField){
throw new ServiceException("导入文件列名:"+field.getName()+"不存在");
}
}
Object[] rowValues;
// 一条条取出path文件中记录
List<E> dataList = Lists.newArrayList();
while ((rowValues = reader.nextRecord()) != null) {
E e = null;
try {
e = (E) cls.newInstance();
} catch (Exception e8) {
}
for (int i = 0; i < rowValues.length; i++) {
DBFField field = reader.getField(i);
Object object = rowValues[i];
System.out.println(i + "-------" + object + "--------" + field.getName());
String val = "";
if (StringUtils.isNotNull(object)) {
val = object.toString();
}
Reflections.invokeSetter(e, field.getName(), val);
}
dataList.add(e);
}
return dataList;
}
public static <T> void exportToDbf(HttpServletResponse response, Class<?> clazz, List<T> dataList,
String fileName) {
try {
response.setContentType("application/x-dbf;");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition",
"attachment; filename=" + URLEncoder.encode(fileName + ".dbf", "UTF-8"));
// 获取字段数量和记录数量
int numFields = getNumFields(clazz);
int numRecords = dataList.size();
// 读取内容转表达式中的值
// setFieldValue(dataList);
// 创建一个包含字段信息的 DBFField 数组
DBFField[] fields = getFields(clazz);
// 创建一个 DBFWriter 对象,用于写入 DBF 文件
// DBFWriter writer = new DBFWriter(response.getOutputStream(), Charset.forName("GBK"));
DBFWriter writer = new DBFWriter(response.getOutputStream(), Charset.forName("GBK"));
writer.setFields(fields);
if (!CollectionUtils.isEmpty(dataList)) {
// 将每个 Person 对象的属性值写入到 DBF 文件中
for (int i = 0; i < numRecords; i++) {
Object[] record = new Object[numFields];
T obj = dataList.get(i);
for (int j = 0; j < numFields; j++) {
record[j] = getFieldValue(obj, j);
}
writer.addRecord(record);
}
}
// 关闭 DBFWriter 对象
writer.close();
} catch (Exception e) {
// log.error(e.getMessage());
throw new RuntimeException(e.getMessage(), e);
}
}
private static <T> int getNumFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
int count = 0;
for (Field field : fields) {
if (field.isAnnotationPresent(Dbf.class)) {
count++;
}
}
return count;
}
private static <T> DBFField[] getFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
int numFields = getNumFields(clazz);
if (numFields < 0) {
numFields = 0;
}
DBFField[] resultFields = new DBFField[numFields];
int index = 0;
boolean flag=false;
for (Field field : fields) {
if (field.isAnnotationPresent(Dbf.class)) {
Dbf fieldNameAnnotation = field.getAnnotation(Dbf.class);
int fieldIndex = fieldNameAnnotation.order();
if (fieldIndex == 0) {
flag=true;
}
if(flag){
fieldIndex = index;
}
String fieldName = fieldNameAnnotation.name();
if (fieldName.length() > 10) {
fieldName = fieldName.substring(0, 10);
}
DBFDataType fieldType = DBFDataType.CHARACTER;
if (field.getType() == int.class || field.getType() == Integer.class) {
fieldType = DBFDataType.NUMERIC;
} else if (field.getType() == double.class || field.getType() == Double.class) {
fieldType = DBFDataType.FLOATING_POINT;
}
resultFields[fieldIndex] = new DBFField(fieldName, fieldType, 20); // 字段类型设置为CHARACTER,长度为10个字符
index++;
}
}
return resultFields;
}
public static <T> void setFieldValue(List<T> dataList) {
try {
for (T t : dataList) {
if (!ObjectUtils.isEmpty(t)) {
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Dbf.class)) {
Dbf fieldNameAnnotation = field.getAnnotation(Dbf.class);
String converterExp = fieldNameAnnotation.readConverterExp();
if (StringUtils.isNotEmpty(converterExp)) {
field.setAccessible(true);
// 读取转换值
if (!ObjectUtils.isEmpty(t)) {
field.set(t, parseConverterExp(field.get(t), converterExp));
}
}
}
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private static Object parseConverterExp(Object o, String converterExp) {
CONVERTER_EXP_MAP = Arrays.stream(converterExp.split(",")).map(s -> s.split("=")).filter(arr -> arr.length == 2)
.collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
return CONVERTER_EXP_MAP.get(o);
}
private static <T> Object getFieldValue(T obj, int index) {
if (ObjectUtils.isEmpty(obj)) {
return null;
}
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Dbf.class)) {
Dbf fieldNameAnnotation = field.getAnnotation(Dbf.class);
int fieldIndex = fieldNameAnnotation.order();
if (fieldIndex == index) {
try {
field.setAccessible(true);
return field.get(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
return null;
}
}