美文网首页
CSV文件和XLS文件有何区别

CSV文件和XLS文件有何区别

作者: junpassion | 来源:发表于2018-08-24 16:39 被阅读127次
    今天在做一个需求时,需要将统计后的结果写入到HDFS上,方便后续业务分析,能够读取到该文件,以邮件附件的形式展示文件的结果。但是发现,最后展示的CSV格式的文件作为邮件附件是没有问题的,但是XLS的文件却出现了很多乱码,如图: 日报乱码.png

    读取csv、xls文件的方法如下:

    val bytes = HdfsUtil.readHdfsFileToByteArray(AttachmentSummary.HDFS_OUTPUT + day +".xls")
    val attaches =Map[String, Array[Byte]](s"附件-$day.xls" -> bytes)
    

    其中readHdfsFileToByteArray方法如下,利用InputStreamReader 去读取文件:

    val fs: FileSystem = FileSystem.get(CONF)
    ...
      def readHdfsFileToByteArray2(fileName: String): Array[Byte] = {
        //val file = new File(fileName)
        var reader: InputStreamReader = null
        try{
          val finput = fs.open(new Path(fileName))
          reader = new InputStreamReader(finput)
          IOUtils.toByteArray(reader)   // use commons.io.IOUtils 
        } finally {
          IOUtils.closeQuietly(reader)  
        }
      }
    
    后来查询相关的资料才发现,csv属于文本文件,而xls是二进制文件,二者有本质区别。 iostream.png

    Reader是用来处理字符流的,所以csv文件是没有问题的,但是用来处理字节流是不行的,所以xls文件乱码。
    后续改为使用ByteArrayOutputStream直接拷贝一个inputStream,这样xls文件是OK的:

      def readHdfsFileToByteArray(fileName: String): Array[Byte] = {
        val finput = fs.open(new Path(fileName))
        val output = new ByteArrayOutputStream()
        try{
          IOUtils.copy(finput, output)
          output.toByteArray
        } finally {
          finput.close()
          output.close()
        }
      }
    

    总结:

    1. 文本文件。像txt,html, csv等格式的文件都属于文本文件。可以使用字符流来处理。
    2. 二进制文件。像xls,word等文件都是二进制文件。若用流来处理,需使用字节流。
    3. 字节流操作的基本单元为字节,通常用于处理二进制数据;字符流操作的基本单元为Unicode码元,通常用于处理文本数据。
    4. 文本文件为了兼容性,最好在写入时,加上BOM头 ByteOrderMark.UTF_8.getBytes,这样打开时,将严格按照指定的编码方式打开,否则不同平台,可能出现乱码。而二进制文件,不存在BOM头一说,只要一个字节写错,整个文件都将乱码。
    5. 判断某文件是文本还是二进制文件,能用NotePad打开不是乱码的是文本文件,打开全是乱码的则是二进制文件。而且对于文本文件,还可以使用Nodepad来转换格式,加BOM头等操作。

    参考资料:
    理解Java中字符流与字节流的区别
    Java 流(Stream)、文件(File)和IO

    相关文章

      网友评论

          本文标题:CSV文件和XLS文件有何区别

          本文链接:https://www.haomeiwen.com/subject/fociiftx.html