获取csv文件编码,解决csv读取中文乱码问题

咱们解析csv文件时最经常遇到的问题就是乱码,可能有朋友说了我在解析时直接设定编码类型为GBK,GB2312就可以解决中文乱码,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static List<List<String>> readTxtOrCsvFile(InputStream input) {
    List<List<String>> data = Lists.newArrayList();
    if (input == null) {
        return data;
    }
    InputStreamReader read = null;
    BufferedReader br = null;
    try {
        read = new InputStreamReader(input, "GB2312");
        br = new BufferedReader(read);
        String line;
        while ((line = br.readLine()) != null) {
            if (StringUtils.isNotBlank(line)) {
                List<String> dd = Arrays.asList(line.split(","));
                List<String> n = new ArrayList<>();
                for (int i = 0; i < dd.size(); i++) {
                    String cellData = dd.get(i);
                    n.add(buildText(cellData));
                }
                data.add(n);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (br != null) {
                br.close();
            }
            if (read != null) {
                read.close();
            }
            if (input != null) {
                input.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return data;
}

 这样可以解决部分用户的乱码,我想问下如果我的文件类型为UTF-8呢,这样解析出来的还是有乱码。如何做到完全解决呢。作者本人也遇到这种问题,想了许久,也在网上搜索很久,得到一个解决方案。

解决方案是:自己获取要解析文件编码,然后按照编码进行解析。如何才能获取编码,有如下步骤

1、从流中读取前三个字节到一个byte[3]数组中;
2、通过Integer.toHexString(byte[0] & 0xFF),将byte[3]数组中的三个byte分别转换成16进制的字符表示;
3、根据对三个byte进行转换后得到的字符串,与UTF-8格式头EFBBBF进行比较即可知道是否UTF-8格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
 * 读取txt,csv文件
 *
 * @return
 */
public static List<List<String>> readTxtOrCsvFile(InputStream input) {
 
    List<List<String>> data = Lists.newArrayList();
    if (input == null) {
        return data;
    }
    InputStreamReader read = null;
    BufferedReader br = null;
    BufferedInputStream bb = null;
    try {
        bb = new BufferedInputStream(input);
        read = new InputStreamReader(bb, getCharSet(bb));
        br = new BufferedReader(read);
        String line;
        while ((line = br.readLine()) != null) {
            if (StringUtils.isNotBlank(line)) {
                List<String> dd = Arrays.asList(line.split(","));
                List<String> n = new ArrayList<>();
                for (int i = 0; i < dd.size(); i++) {
                    String cellData = dd.get(i);
                    n.add(buildText(cellData));
                }
                data.add(n);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (br != null) {
                br.close();
            }
            if (read != null) {
                read.close();
            }
            if (bb != null) {
                bb.close();
            }
            if (input != null) {
                input.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return data;
}
 
 
/**
 * 获取流对应的编码类型
 * @param bb
 * @return
 * @throws Exception
 */
private static String getCharSet(BufferedInputStream bb) throws Exception {
 
    String charSet = null;
    byte[] buffer = new byte[3];
    //因流读取后再读取可能会缺少内容,此处需要先读,然后再还原
    bb.mark(bb.available() + 1);
    bb.read(buffer);
    bb.reset();
    String s = Integer.toHexString(buffer[0] & 0xFF) + Integer.toHexString(buffer[1] & 0xFF) + Integer.toHexString(buffer[2] & 0xFF);
    switch (s) {
        //GBK,GB2312对应均为d5cbba,统一当成GB2312解析
        case "d5cbba":
            charSet = "GB2312";
            break;
        case "efbbbf":
            charSet = "UTF-8";
            break;
        default:
            charSet = "GB2312";
            break;
    }
 
    return charSet;
}

 问题圆满解决

posted @   飞翔的阿宝  阅读(5019)  评论(0)    收藏  举报
编辑推荐:
· MySQL索引完全指南:让你的查询速度飞起来
· 一个字符串替换引发的性能血案:正则回溯与救赎之路
· 为什么说方法的参数最好不要超过4个?
· C#.Net 筑基-优雅 LINQ 的查询艺术
· 一个自认为理想主义者的程序员,写了5年公众号、博客的初衷
阅读排行:
· 使用GcExcel .NET将Excel导出为PDF
· 【设计模式】外观模式
· 本地搭建一个对嘴AI工具
· MySQL索引完全指南:让你的查询速度飞起来
· Web前端入门第 72 问:JavaScript DOM 内容操作常用方法和 XSS 注入攻击
点击右上角即可分享
微信分享提示