解析文件,即把文件每条数据解析成一个对象

package com.lhx.test;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.lhx.test.utils.CSVRead;
import com.lhx.test.utils.StringValidate;
import org.junit.Test;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by Li hongxin on 2019/6/19
 * Desc : 解析list里面的数据,转换成对象
 */
public class ParseList {

    private static final String SPLIT_SYMBOL = "_";
    private static final String array[] = {
            "java.lang.String",
            "java.lang.Long",
            "long",
            "java.lang.Integer",
            "int",
            "java.lang.Boolean",
            "boolean",
            "java.lang.Double",
            "double",
            "java.lang.Float",
            "float",
            "java.lang.Character",
            "char",
            "java.lang.Short",
            "short",
            "java.lang.Byte",
            "byte",
            "java.util.Date"
    };

    private static final String REGEX1 = "(\\d{4})/(\\d{1,2})/(\\d{1,2})";
    private static final String REGEX2 = "(\\d{4})-(\\d{2})-(\\d{2})";
    private static final String REGEX3 = "(\\d{4})/(\\d{1,2})/(\\d{1,2}) (\\d{2}):(\\d{2}):(\\d{2})";
    private static final String REGEX4 = "(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})";

    private static final String TEMPLATE1 = "yyyy/MM/dd";
    private static final String TEMPLATE2 = "yyyy-MM-dd";
    private static final String TEMPLATE3 = "yyyy/MM/dd hh:mm:ss";
    private static final String TEMPLATE4 = "yyyy-MM-dd hh:mm:ss";

    private static final Pattern pattern1 = Pattern.compile(REGEX1);
    private static final Pattern pattern2 = Pattern.compile(REGEX2);
    private static final Pattern pattern3 = Pattern.compile(REGEX3);
    private static final Pattern pattern4 = Pattern.compile(REGEX4);

    private static final SimpleDateFormat sdf1 = new SimpleDateFormat(TEMPLATE1);
    private static final SimpleDateFormat sdf2 = new SimpleDateFormat(TEMPLATE2);
    private static final SimpleDateFormat sdf3 = new SimpleDateFormat(TEMPLATE3);
    private static final SimpleDateFormat sdf4 = new SimpleDateFormat(TEMPLATE4);

    // 测试
    public static <T> void testThread(String path, String charset, char elementSeparator, char quoteChar, Class<T> clz, boolean underlined) throws Exception {
        DataInputStream in = new DataInputStream(new FileInputStream(new File(path)));
        BufferedReader reader= new BufferedReader(new InputStreamReader(in,charset));
        CSVRead csvRead = new CSVRead(reader, elementSeparator, quoteChar);
        List<ArrayList<String>> lists = csvRead.readFile();
        System.out.println(Thread.currentThread() + "---------" + JSON.toJSONString(toJavaBean(lists, clz, underlined)));
    }

    /**
     * Created by lhx on 2019/6/19 17:30
     * Desc : 把数据转换成任何指定泛型的对象集合,根据对象的属性获取对应属性下的转换后的值并进行赋值
     * outer        数据集合
     * clz          要转换成的对象
     * underlined   CSV文件中的字段名是否为下划线格式的
     */
    public static <T> List<T> toJavaBean(List<ArrayList<String>> outer, Class<T> clz, boolean underlined) throws Exception {
        if (null == outer || outer.size() < 2) {
            return null;
        }
        List<T> resultList = new ArrayList<T>();

        //先转换原文件中获取的字段名为驼峰格式的
        ArrayList<String> originalNames = outer.get(0);
        int fieldCount = originalNames.size();
        if (underlined) {
            //如果是下划线格式的,则转换为驼峰格式的
            toCamelCase(originalNames);
        }

        //初始化两个集合,接收bean对象的有效字段名和字段对应的类型
        List<String> beanFieldNames = new ArrayList<String>(fieldCount);
        List<String> fieldTypes = new ArrayList<String>(fieldCount);

        //递归取出当前类和父类以及更高级的类的所有除Object类之外的字段以及属性
        recurrenceFetch(beanFieldNames, fieldTypes, originalNames, clz);
        List<String> _beanFieldNames = getList(String.class, fieldCount);
        List<String> _fieldTypes = getList(String.class, fieldCount);
        List<Integer> _index = getList(Integer.class, fieldCount);
        for (int i = 0; i < fieldCount; i++) {
            String _fieldName = originalNames.get(i);
            if (beanFieldNames.contains(_fieldName)) {
                //如果此索引下含有该字段名,则记录该字段名,字段属性,在原数据list的索引位置,
                _beanFieldNames.set(i, _fieldName);
                _fieldTypes.set(i, fieldTypes.get(beanFieldNames.indexOf(_fieldName)));
                _index.add(i);
            }
        }

        //解析数据
        for (int dataIndex = 1; dataIndex < outer.size(); dataIndex++) {
            ArrayList<String> inner = outer.get(dataIndex);
            T newInstance = clz.newInstance();
            for (int i = 0; i < Math.min(inner.size(), fieldCount); i++) {
                // 递归给当前类和父类和除了Object之外的超类赋值
                newInstance = recurrenceAssign(_index, _beanFieldNames, _fieldTypes, inner, newInstance, clz, i);
            }
            resultList.add(newInstance);
        }
        return resultList;
    }

    // 返回指定类型和长度的集合并进行初始化
    private static <T> List<T> getList(Class<T> clz, int initSize) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        if (0 >= initSize) {
            return new ArrayList<T>(0);
        }
        //ArrayList初始化长度为10,大于10的则按照arrayList底层扩容算法进行扩容
        initSize = initSize < 10 ? 10 : (initSize + (initSize >> 1));
        List<T> list = new ArrayList<T>(initSize);
        int count = 0;
        String className = clz.getName();

        while (count < initSize) {
            T newInstance;
            if (array[0].equals(className)) {
                newInstance = clz.getConstructor(String.class).newInstance("");
            } else if (array[1].equals(className)) {
                newInstance = clz.getConstructor(long.class).newInstance(-1L);
            } else if (array[3].equals(className)) {
                newInstance = clz.getConstructor(int.class).newInstance(-1);
            } else if (array[7].equals(className)) {
                newInstance = clz.getConstructor(double.class).newInstance(-1);
            } else {
                newInstance = null;
            }
            list.add(newInstance);
            count++;
        }
        return list;
    }

    // 递归给当前类和除了Object之外的超类赋值
    private static  <T> T recurrenceAssign(List<Integer> _index, List<String> _beanFieldNames, List<String> _fieldTypes, ArrayList<String> inner, T newInstance, Class<?> clz, int i) {
        if (_index.contains(i)) {
            String fieldName = _beanFieldNames.get(i);
            String fieldType = _fieldTypes.get(i);
            String value = inner.get(i);
            Object realValue = getRealValue(fieldType, value);
            Field field;
            try {
                if ("isNew".equals(fieldName)) {
                    realValue = dealNum((String)realValue);
                }
                field = clz.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(newInstance, realValue);
            } catch (Exception e) {
                //当前类没有此字段,去父类中找, 如果匹配上,则进行赋值,直到匹配到Object为止,
                // 如果匹配不到,抛出java.lang.NoSuchFieldException异常,catch到之后进行递归父类的字段,
                if (e instanceof NoSuchFieldException) {
                    Class<?> superclass = newInstance.getClass().getSuperclass();
                    if (Object.class != superclass) {
                        recurrenceAssign(_index, _beanFieldNames, _fieldTypes, inner, newInstance, superclass, i);
                    }
                }
            }
        }
        return newInstance;
    }

    //递归迭代出本对象以及除Object之外所有超类的属性
    private static void recurrenceFetch(List<String> beanFieldNames, List<String> fieldTypes, ArrayList<String> originalNames, Class<?> clz) {
        Field[] fields = clz.getDeclaredFields();
        if (Object.class != clz) {
            iterate(beanFieldNames, fieldTypes, originalNames, fields);
            Class<?> superclass = clz.getSuperclass();
            recurrenceFetch(beanFieldNames, fieldTypes, originalNames, superclass);
        }
    }

    //迭代出所有属性名和属性
    private static void iterate(List<String> beanFieldNames, List<String> fieldTypes, ArrayList<String> originalNames, Field[] fields) {
        for (Field field : fields) {
            String name = field.getName();
            if (originalNames.contains(name)) {
                beanFieldNames.add(name);
                fieldTypes.add(field.getType().getName());
            }
        }
    }

    //把有效值进行翻译成每个字段对应的属性所对应的值
    private static Object getRealValue(final String fieldType, String value) {
        String[] comparedArray = array;
        if (comparedArray[0].equals(fieldType)) {
            value = dealNum(value);
            return value;
        }
        if (comparedArray[1].equals(fieldType) || comparedArray[2].equals(fieldType)) {
            value = dealNum(value);
            return Long.valueOf(value);
        }
        if (comparedArray[3].equals(fieldType) || comparedArray[4].equals(fieldType)) {
            value = dealNum(value);
            return Integer.valueOf(value);
        }
        if (comparedArray[5].equals(fieldType) || comparedArray[6].equals(fieldType)) {
            return Boolean.valueOf(value);
        }
        if (comparedArray[7].equals(fieldType) || comparedArray[8].equals(fieldType)) {
            return Double.valueOf(value);
        }
        if (comparedArray[9].equals(fieldType) || comparedArray[10].equals(fieldType)) {
            return Float.valueOf(value);
        }
        if (comparedArray[11].equals(fieldType) || comparedArray[12].equals(fieldType)) {
            return value.charAt(0);
        }
        if (comparedArray[13].equals(fieldType) || comparedArray[14].equals(fieldType)) {
            value = dealNum(value);
            return Short.valueOf(value);
        }
        if (comparedArray[15].equals(fieldType) || comparedArray[16].equals(fieldType)) {
            value = dealNum(value);
            return Byte.valueOf(value);
        }
        if (comparedArray[17].equals(fieldType)) {
            return parseDate(value);
        }
        return value;
    }

    //处理数字,由于CSV文件生成的时候,数字都会带小数点,如:21.0/39.0/0.0等,导致解析为int或者long类型的时候,报错.解析之后返回小数点之前的数字
    public static String dealNum(String str) {
        if (StringUtils.isBlank(str)) {
            return "";
        }
        if (Pattern.compile("(\\d+)\\.(\\d+)").matcher(str).matches()) {
            str = str.substring(0, str.indexOf("."));
        }
        return str;
    }

    //解析时间,如果不符合正则列举的这几种,则无法解析,返回null,别的类型会报错
    private static Date parseDate(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        try {
            if (pattern1.matcher(value).matches()) {
                return sdf1.parse(value);
            }
            if (pattern2.matcher(value).matches()) {
                return sdf2.parse(value);
            }
            if (pattern3.matcher(value).matches()) {
                return sdf3.parse(value);
            }
            if (pattern4.matcher(value).matches()) {
                return sdf4.parse(value);
            }
        } catch (ParseException e) {
            return null;
        }
        return null;
    }

    /**
     * Created by lhx on 2019/6/19 17:44
     * Desc : 下划线格式转换为驼峰格式
     * fileNames        要进行转换的数据
     * beanFieldsName   要转换到对象的对象名
     * @returns         返回驼峰格式的数据
     */
    private static void toCamelCase(ArrayList<String> fieldNames) {

        if (CollectionUtils.isEmpty(fieldNames)) {
            return;
        }
        for (int i = 0; i < fieldNames.size(); i++) {
            String fieldName = fieldNames.get(i);
            if (StringValidate.isNotBlank(fieldName)) {
                fieldName = fieldName.toLowerCase();
                if (fieldName.contains(SPLIT_SYMBOL)) {
                    String[] split = fieldName.split(SPLIT_SYMBOL);
                    String temp = split[0];
                    for (int j = 1; j < split.length; j++) {
                        String str = split[j];
                        temp = temp + str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
                    }
                    fieldName = temp;
                }
                //使用驼峰格式替换下划线格式
                fieldNames.set(i, fieldName);
            }
        }
    }

    //去驼峰,转为下划线
    private static void deCamelCase(ArrayList<String> fieldNames) {

        if (CollectionUtils.isEmpty(fieldNames)) {
            return;
        }
        for (int i = 0; i < fieldNames.size(); i++) {
            String fieldName = fieldNames.get(i);
            if (StringValidate.isNotBlank(fieldName)) {
                //去空格
                fieldName = fieldName.replace(" ", "");
                //逐个字符遍历
                StringBuilder sb = new StringBuilder(16);
                for (Character chr : fieldName.toCharArray()) {
                    if (Character.isLetter(chr)) {
                        if (Character.isUpperCase(chr)) {
                            chr = Character.toLowerCase(chr);
                            sb.append(SPLIT_SYMBOL).append(chr);
                        } else {
                            sb.append(chr);
                        }
                    } else {
                        sb.append(chr);
                    }
                }
                fieldName = sb.toString().toUpperCase();
                //使用驼峰格式替换下划线格式
                fieldNames.set(i, fieldName);
            }
        }
    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值