• csv文件导出注意事项


    一、中文乱码问题

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

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

            /**
             * utf-8的bom头
             */
            byte[] UTF8_HEADER_BOM = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};

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

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

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

    可在文本后加 解决

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

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

            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);
    

      

    完整示例:

        /**
         * 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 = "编号,品名,时间戳
    ".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 + "	,");
                    sb.append("产品" + j + ",");
                    sb.append(timestamp + "	
    ");
                }
                byte[] data = sb.toString().getBytes("UTF-8");
                mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, file.length(), data.length);
                mappedByteBuffer.put(data);
            }
    
            //关闭通道
            channel.close();
        }
    

    导出效果:

  • 相关阅读:
    爬取校园新闻首页的新闻
    网络爬虫基础练习
    【mongoDB实战】mongo集群---主从复制篇
    【mongoDB实战】聚合管道--$unwind
    【mongoDB实战】聚合管道--$unwind
    【mongoDB实战】mongoDB数据导入和导出
    【mongoDB实战】mongoDB数据导入和导出
    【mongoDB实战】mongoDB数据备份和还原
    【mongoDB实战】mongoDB数据备份和还原
    【Restful】三分钟彻底了解Restful最佳实践
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/how-to-export-csv.html
Copyright © 2020-2023  润新知