前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >csv文件导出注意事项

csv文件导出注意事项

作者头像
菩提树下的杨过
发布2020-06-24 10:09:38
1.4K0
发布2020-06-24 10:09:38
举报

一、中文乱码问题

默认情况下,在windows上用excel打开csv文件时,并不是按utf-8码解析的,就算代码里设置了写入字符串为utf-8字符集,也可能乱码。

需要在文件头写入几个特殊的字节,做为utf-8的BOM头。

代码语言:javascript
复制
        /**
         * utf-8的bom头
         */
        byte[] UTF8_HEADER_BOM = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};

建议导出后,用一些编辑工具查看16进制格式,确认前3个字节是否ef bb bf

二、大数字被显示为科学计数法的问题

一些产品编码,比如100000000001,打开后,会变成:

可在文本后加\t解决

三、海量数据写入时如何避免OOM

通常我们会把内容先拼成一个String,然后一次性写入,如果数据量巨大,比如上千万,一次性拼接很容易造成OOM。可以借用内存映射(NIO中的技术)优化。

代码语言:javascript
复制
        RandomAccessFile file = new RandomAccessFile(csvFileName, "rw");
        FileChannel channel = file.getChannel();
        MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, file.length(), UTF8_HEADER_BOM.length);
        mappedByteBuffer.put(UTF8_HEADER_BOM);

完整示例:

代码语言:javascript
复制
    /**
     * csv写入示例(菩提树下的杨过 http://yjmyzz.cnblogs.com)
     *
     * @throws IOException
     */
    private static void testCsv() throws IOException {
        /**
         * utf-8的bom头
         */
        byte[] UTF8_HEADER_BOM = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};

        String csvFileName = "D:\\temp\\test.csv";
        FileUtils.deleteQuietly(new File(csvFileName));

        RandomAccessFile file = new RandomAccessFile(csvFileName, "rw");
        FileChannel channel = file.getChannel();


        byte[] header = "编号,品名,时间戳\n".getBytes("UTF-8");

        //写入utf8的bom头,防止打开csv时显示乱码
        MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, file.length(), UTF8_HEADER_BOM.length);
        mappedByteBuffer.put(UTF8_HEADER_BOM);

        //写入标题栏
        mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, file.length(), header.length);
        mappedByteBuffer.put(header);

        //分批写入记录(每批1000条)-防止OOM
        long timestamp = System.currentTimeMillis();
        for (int i = 1; i <= 100; i++) {
            StringBuilder sb = new StringBuilder();
            for (int j = 1; j <= 1000; j++) {
                sb.append(i * j + "\t,");
                sb.append("产品" + j + ",");
                sb.append(timestamp + "\t\n");
            }
            byte[] data = sb.toString().getBytes("UTF-8");
            mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, file.length(), data.length);
            mappedByteBuffer.put(data);
        }

        //关闭通道
        channel.close();
    }

导出效果:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档