fastCSV实现csv文件内容的读取和生成

   这两天需要做一个将CSV文件内容上传至数据库中,进行持久化,我的思路是先进行读取出来,然后进行一行一行插入数据库中。这种思路目前来说可能没问题,因为涉及的数据较少,如果涉及较多的数据可能就会出现加载过慢的问题,那么就需要做代码优化。
   我的CSV文件是通过爬虫从第三方数据库中爬取得到的,里面的内容格式也是各种各样。因为自己还年轻,就直接想到了以流的形式进行读取。代码如下:

InputStreamReader isr = new InputStreamReader(new FileInputStream(path), "UTF-8");
        BufferedReader reader = new BufferedReader(isr);
        int i = 0;
        int a = 0;
        try {
    
    
            String line = null;
            while((line=reader.readLine())!=null){
    
    
                String[] item = line.split(",",-1);//CSV格式文件为逗号分隔符文件,这里根据逗号切分
                System.out.println("长度:"+item.length);
                String str = item[1];
                //item[1]为价格,且为字符串,将字符串中的小数进行提取出来
                // 控制正则表达式的匹配行为的参数(小数)
                Pattern p = Pattern.compile("(\\d+\\.\\d+)");
                //Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例.
                Matcher m = p.matcher(str);
                //m.find用来判断该字符串中是否含有与"(\\d+\\.\\d+)"相匹配的子串
                if (m.find()) {
    
    
                    //如果有相匹配的,则判断是否为null操作
                    //group()中的参数:0表示匹配整个正则,1表示匹配第一个括号的正则,2表示匹配第二个正则,在这只有一个括号,即1和0是一样的
                    str = m.group(1) == null ? "" : m.group(1);
                } else {
    
    
                    //如果匹配不到小数,就进行整数匹配
                    p = Pattern.compile("(\\d+)");
                    m = p.matcher(str);
                    if (m.find()) {
    
    
                        //如果有整数相匹配
                        str = m.group(1) == null ? "" : m.group(1);
                    } else {
    
    
                        //如果没有小数和整数相匹配,即字符串中没有整数和小数,就设为空
                        str = "";
                    }
                }
                System.out.println("我是:"+str);
                DataInfo dataInfo=new DataInfo();
                System.out.println("item的长度:"+item.length);
                //将英文逗号转换成中文逗号
                System.out.println("原始名字:"+item[0]);
                String b = ",";
                String str0 = item[0].replaceAll(",",b);

                System.out.println("item[0]:"+str0);
                System.out.println("item[1]:"+str);
                System.out.println("item[2]:"+item[2]);
                System.out.println("item[3]:"+item[3]);
                if (item[2].length() == 0){
    
    
                    item[2] = "0";
                }
                if (item[3].length() == 0){
    
    
                    item[3] = "0";
                }
                if (str.length() == 0){
    
    
                    str = "0";
                }
                dataInfo.setName(str0);
                dataInfo.setPrice(str);
                dataInfo.setLatitude(item[2]);
                dataInfo.setLongitude(item[3]);
                dataInfo.setCreateDate(current);
                System.out.println("DataInfo的值:"+dataInfo);
                String[] split = fileName.split("-");
                System.out.println("split444:"+split[1]);

                //取第二个值
                if (split[1].equals("newhouse")){
    
    
                    System.out.println("hahahaha1111");
                    i = intoMapper.intoNewsMapper(dataInfo);
                    a=a+1;
                }else if (split[1].equals("secondhouse")){
    
    
                    i = intoMapper.intoSecondMapper(dataInfo);
                    a=a+1;
                }else if (split[1].equals("rentinghouse")){
    
    
                    i = intoMapper.intoRentMapper(dataInfo);
                    a=a+1;
                }
            }
        }finally {
    
    
            reader.close();
            }

   大致思路就是通过InputStreamReader isr = new InputStreamReader(new FileInputStream(path), "UTF-8"); BufferedReader reader = new BufferedReader(isr)以流的形式进行全部读取,然后再通过循环行line=reader.readLine()进行遍历出来,然后再进行将每行的数据分割出来,插入到数据库中。问题就出现在行分割上面,因为是通过爬虫从第三方爬取出来的数据,格式完全不一样,有换行啦,有英文逗号啦,反正就是不可预测的各种格式,本身没办法预测更不要说进行处理这些数据了。当遇到换行问题时还好进行处理,遇到从一段文字中提取出来小数或者整数的时候也好进行处理,最难的是遇到英文逗号“,”了是最难处理的,英文你读取的数据本身每一列隔开就是用英文逗号分割开来的,读取后的内容如下图所示:

整租·山海梧桐 11厅 南/,2750/,22.561189,114.2286
整租·鸿荣源·壹城中心第八区 11厅 南,1820/,22.6527136689,114.0360039841
整租·龙光玖云著 21厅 南,2800/,22.685514,114.337256
整租·共和花园 10厅 南,1350/,22.654156577768,114.04290481474
整租·茂业城 11厅 东南,1800/,22.617428,114.140558
整租·向南一区 10厅 东南,1699/,22.628218357484,114.04349583641
整租·锦城星苑 21厅 北,2200/,22.751925445789,114.2864754459
整租·光明142厅 东南,3000/,22.740888,113.935798
整租·财富城 32厅 东南,2000/,22.708919,114.346404
整租·百合盛世二期 31厅 西北,1800/,22.750213,114.244653
整租·麓园 42厅 东南,2000/,22.73853,114.22597
整租·军裕公寓 10厅 东,1980/,22.601874,113.855116
整租·宏发雍景城 22厅 南/,3800/,22.785978,113.912478
整租·元芬花园 10厅 东南//西南,1299/,22.660840985621,114.00942180444
整租·奥园峯荟 22厅 复式 西南,3200/,22.771239,113.904964
整租·又一城 22厅 东南/,1800/,22.731801,114.220185
整租·茂业城 10厅 西北,1800/,22.617428,114.140558
整租·茂业城 11厅 东南,2000/,22.617428,114.140558
合租·深业新岸线三期 1居室 西南卧,1900/,22.565182,113.879114
整租·德兴城花园 11厅 南/西南,2300/,22.614861,114.120201
合租·麟恒中心广场一期 3居室 东南卧,1700/,22.643806,114.19315

   你看文件内容中有英文逗号,读取的内容列于列之间又是通过“,”进行分割的,你也不知道文件内容中何时出来英文逗号。当时第一反应是把所有的内容中的逗号全部replaceAll()替换为中文逗号,但是你要直接替换,那就出现把列与列之间的英文逗号也进行替换,因此不可行;当时想到先进行分割进行替换,写了之后还进行报错,最后想起来分割后替换已经晚了,因为文件内容中的英文逗号已经进行分割,所以这种方式还是失败的。最后问了老大,给了个思路,利用fastCSV工具进行读取文件。
   下面讲下怎么使用fastCSV这个工具:
首先导入fastCSV依赖:

<dependency>
            <groupId>de.siegmar</groupId>
            <artifactId>fastcsv</artifactId>
            <version>1.0.3</version>
</dependency>

然后是代码实现

CsvReader csvReader = new CsvReader();
            CsvReader fileReader = new CsvReader();
            CsvContainer csvFile = fileReader.read(file, Charset.forName("UTF-8"));
                if(csvFile!=null){
    
    
                    for (CsvRow rowfiles : csvFile.getRows()) {
    
    
                        String str = rowfiles.getField(1);
                        //item[1]为价格,且为字符串,将字符串中的小数进行提取出来
                        // 控制正则表达式的匹配行为的参数(小数)
                        Pattern p = Pattern.compile("(\\d+\\.\\d+)");
                        //Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例.
                        Matcher m = p.matcher(str);
                        //m.find用来判断该字符串中是否含有与"(\\d+\\.\\d+)"相匹配的子串
                        if (m.find()) {
    
    
                            //如果有相匹配的,则判断是否为null操作
                            //group()中的参数:0表示匹配整个正则,1表示匹配第一个括号的正则,2表示匹配第二个正则,在这只有一个括号,即1和0是一样的
                            str = m.group(1) == null ? "" : m.group(1);
                        } else {
    
    
                            //如果匹配不到小数,就进行整数匹配
                            p = Pattern.compile("(\\d+)");
                            m = p.matcher(str);
                            if (m.find()) {
    
    
                                //如果有整数相匹配
                                str = m.group(1) == null ? "" : m.group(1);
                            } else {
    
    
                                //如果没有小数和整数相匹配,即字符串中没有整数和小数,就设为空
                                str = "";
                            }
                        }
                        String a2 = rowfiles.getField(2);
                        String a3 = rowfiles.getField(3);
                        if (rowfiles.getField(2).length() == 0){
    
    
                            a2 = "0";
                        }
                        if (rowfiles.getField(3).length() == 0){
    
    
                            a3 = "0";
                        }
                        if (str.length() == 0){
    
    
                            str = "0";
                        }
                        DataInfo dataInfo=new DataInfo();
                        dataInfo.setName(rowfiles.getField(0));
                        dataInfo.setPrice(str);
                        dataInfo.setLatitude(a2);
                        dataInfo.setLongitude(a3);
                        String[] split = fileName.split("-");

                        //取第二个值
                        if (split[1].equals("newhouse")){
    
    
                            i = intoMapper.intoNewsMapper(dataInfo);
                            a=a+1;
                        }else if (split[1].equals("secondhouse")){
    
    
                            i = intoMapper.intoSecondMapper(dataInfo);
                            a=a+1;
                        }else if (split[1].equals("rentinghouse")){
    
    
                            i = intoMapper.intoRentMapper(dataInfo);
                            a=a+1;
                        }
                    }
                }

上面是我的代码,下面给大家介绍一下使用它的三种方式:
第一种:

public static List<ResultInfo> csvReadOperation() throws IOException {
    
    
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateString = formatter.format(currentTime);
        System.out.println("startTime:"+dateString);
        File file = new File("/Users/xxx/Desktop/testCSVReader.csv");
        CsvReader csvReader = new CsvReader();
        csvReader.setContainsHeader(true); //表示文件包含表头
        List<ResultInfo> listResultInfo = new ArrayList<>();
        CsvContainer csv = csvReader.read(file, StandardCharsets.UTF_8);
        for (CsvRow row : csv.getRows()) {
    
    
            if (row.getOriginalLineNumber() != 1) {
    
     //同样是为了去掉表头
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setUserId(row.getField(0));
                resultInfo.setUserPhone(row.getField(1));
                resultInfo.setUserName(row.getField(2));
                resultInfo.setRegistTime(row.getField(3));
                resultInfo.setUserlevel(row.getField(4));
                resultInfo.setAppName(row.getField(5));
                listResultInfo.add(resultInfo);
            }
        }
        return listResultInfo;
    }

第二种方式:有时候文件中包含空行,如果想跳过空行,需要设置属性

public static List<ResultInfo> csvReadOperation1() throws IOException {
    
    
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateString = formatter.format(currentTime);
        System.out.println("startTime:"+dateString);
        File file = new File("/Users/fengyanjie/Desktop/test1CSVReader.csv");
        CsvReader csvReader = new CsvReader();
        csvReader.setContainsHeader(true);
        csvReader.setSkipEmptyRows(true);//设置跳过空行
        CsvContainer csv = csvReader.read(file, StandardCharsets.UTF_8);
        List<ResultInfo> listResultInfo = new ArrayList<>();
        System.out.println("文件list大小:"+csv.getRows().size());
        for (CsvRow row : csv.getRows()) {
    
    
            if (row.getOriginalLineNumber() != 1 && "" !=row.getFields().get(0)) {
    
    
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setUserId(row.getField(0));
                resultInfo.setUserPhone(row.getField(1));
                resultInfo.setUserName(row.getField(2));
                resultInfo.setRegistTime(row.getField(3));
                resultInfo.setUserlevel(row.getField(4));
                resultInfo.setAppName(row.getField(5));
                listResultInfo.add(resultInfo);
            }

        }
        return listResultInfo;
    }

第三种:

public static List<ResultInfo> csvReadOperation2() throws IOException {
    
    
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateString = formatter.format(currentTime);
        System.out.println("startTime:"+dateString);
        File file = new File("/Users/fengyanjie/Desktop/test1CSVReader.csv");
        CsvReader csvReader = new CsvReader();
        List<ResultInfo> listResultInfo = new ArrayList<>();
        try (CsvParser csvParser = csvReader.parse(file, StandardCharsets.UTF_8)) {
    
    
            CsvRow row;
            while ((row = csvParser.nextRow()) != null) {
    
    
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setUserId(row.getField(0));
                resultInfo.setUserPhone(row.getField(1));
                resultInfo.setUserName(row.getField(2));
                resultInfo.setRegistTime(row.getField(3));
                resultInfo.setUserlevel(row.getField(4));
                resultInfo.setAppName(row.getField(5));
                listResultInfo.add(resultInfo);

            }
        }
        return listResultInfo ;
    }

生成CSV文件:

   不罗嗦了直接上代码:

//指定路径和编码
CsvWriter writer = CsvUtil.getWriter("e:/testWrite.csv", CharsetUtil.CHARSET_UTF_8);
//按行写出
writer.write(
    new String[] {
    
    "a1", "b1", "c1"}, 
    new String[] {
    
    "a2", "b2", "c2"}, 
    new String[] {
    
    "a3", "b3", "c3"}
);

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45150104/article/details/109476893