`
rmzdb
  • 浏览: 81682 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

【原】UTF-8编码不得不说的事情

 
阅读更多
    一贯都喜欢用UTF-8作为系统的编码方式。但是项目中做了一个上传的操作,直接将xml字符串存库。
        流读取的时候用的是utf-8编码,上传的文件也是utf-8编码,怎么上传后就乱码了?乱的也不是很离谱,就
        在文件的头部,多了一个?字符。可是上传之前的日志输出:没有任何问题。“?”这个字符是从哪里来的。
        百度一番,原来utf-8还有 带不带BOM 之分。
  BOM: Byte Order Mark
  UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支援UTF-16,UTF-32才加上的BOM,BOM签名的意思就是告诉编辑器当前文件采用何种编码,
  方便编辑器识别,但是BOM虽然在编辑器中不显示,但是会产生输出。
  如果通过java写的UTF-8文件,使用Java可以正确的读,但是如果用记事本将相同的内容使用UTF-8格式保存,则在使用程序读取是会从文件中多读出一个不可见字符。
 
  public static void main(String[] args) throws IOException {
  File f = new File("C:/utf.txt");
  FileInputStream in = new FileInputStream(f);
        // 指定读取文件时以UTF-8的格式读取
  BufferedReader br = new BufferedReader(new InputStreamReader(in,
    "UTF-8"));
  String line = br.readLine();
  while (line != null) {
   byte[] allbytes = line.getBytes("UTF-8");     
            for (int i=0; i < allbytes.length; i++)    
            {    
                int tmp = allbytes[i];    
                String hexString = Integer.toHexString(tmp);    
                // 1个byte变成16进制的,只需要2位就可以表示了,取后面两位,去掉前面的符号填充    
                hexString = hexString.substring(hexString.length() -2);    
                System.out.print(hexString.toUpperCase());    
                System.out.print(" ");    
            }   

   System.out.println(line);
   line = br.readLine();
  }

 }
 
输出结果如下:

引用

EF BB BF 54 68 69 73 20 69 73 20 74 68 65 20 66 69 72 73 74 20 6C 69 6E 65 2E
?This is the first line.
54 68 69 73 20 69 73 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E
This is second line.


红色部分的"EF BB BF"刚好是UTF-8文件的BOM编码,可以看出Java在读文件时没能正确处理UTF-8文件的BOM编码,将前3个字节当作文本内容来处理了。


解决办法:
引用
    JDK Bug 4508058

Java InpuStreamReader will support BOM mark for UTF-16 files. But for some reason it does not recognize UTF-8 BOM marks. This is very unfortunate all Windows (>win2k) users if textfiles are saved with Notepad using UTF-8 format. Notepad will add BOM bytes at the start of file, but Java's InputStreamReader does not skip it.

UnicodeInputStream.java class will help you to autorecognize and skip BOMs. This will support UTF-8 as well.

UnicodeReader.java class will do everything ever more transparently. Just instantiate it and read text.

1.通过上面的描述,我们可以发现 inputStream 没有对其处理,但是   UnicodeInputStream 和 UnicodeReader 就可以解决这个问题。
  BufferedReader br = new BufferedReader(new UnicodeReader(in, Charset.defaultCharset().name())); 
  
2.我们自己可以去写程序跳过这个BOM标志。
 
 /**
  * 读取流中前面的字符,看是否有bom,如果有bom,将bom头先读掉丢弃
  * 
  * @param in
  * @return
  * @throws IOException
  */
 public static InputStream trimBOM(InputStream in) throws IOException {

  PushbackInputStream testin = new PushbackInputStream(in);
  int ch = testin.read();
  if (ch != 0xEF) {
   testin.unread(ch);
  } else if ((ch = testin.read()) != 0xBB) {
   testin.unread(ch);
   testin.unread(0xef);
  } else if ((ch = testin.read()) != 0xBF) {
   throw new IOException("错误的UTF-8格式文件");
  } else {
   // 不需要做,这里是bom头被读完了
   // // System.out.println("still exist bom");

  }
  return testin;

 }
编辑器的问题:

               win 记事本 保存的utf-8格式文件是带有BOM。
               notepad++ 保存的utf-8 也是带有BOM的,但是他提供了编码方式 : UTF-8 无 BOM 编码方式
               editplus 保存的utf-8 是不带BOM的  其提供了编码方式: UTF-8 + bom
分享到:
评论

相关推荐

    UTF-8toGBK_labview编码gbk_LabVIEWUTF-8_utf-8toGbk_

    在LabVIEW编程环境中,"UTF-8toGBK.vi"这个程序可能是一个用户自定义的VI(Virtual Instrument),用于将UTF-8编码的字符串转换为GBK编码。LabVIEW作为一个图形化编程语言,提供了丰富的字符串处理函数,其中包括了...

    中文-UTF-8编码转换器

    标题中的“中文-UTF-8编码转换器”指的是一个软件工具,它的主要功能是帮助处理中文和其他特殊字符在UTF-8编码环境下可能出现的乱码问题。UTF-8是一种广泛使用的Unicode字符编码方案,它可以表示Unicode标准中的所有...

    UTF-8编码转换器

    总的来说,“UTF-8编码转换器”是一个实用的工具,对于那些需要处理多种语言文本或者在不同系统间交换数据的人来说非常有价值。通过它可以轻松解决编码兼容性问题,使得数据在不同环境中的传输和使用更加顺畅。

    PB9转换utf-8例子

    标题中的“PB9转换utf-8例子”指的是在PowerBuilder 9(PB9)环境下将数据从非UTF-8编码转换为UTF-8编码的一种解决方案。由于PB9本身不直接支持这种转换,开发者通常需要利用外部库或者特定的编程技巧来实现这个功能...

    UTF-8 编码转换工具

    UTF-8编码是一种广泛...了解UTF-8编码的工作原理和应用场景,对于从事IT工作的人来说是必不可少的基础知识。在实际工作中,无论是开发网页、编写代码还是处理多语言文本,掌握UTF-8的使用都能大大提升效率和准确性。

    Delphi和JAVA进行TCPIP通信(用UTF-8编码)例子

    因为不太熟悉java语言,还曾经怀疑是不是Delphi的utf-8编码和java语言的不一样。 最近学习了一下java的相关知识,写一个小程序来测试验证一下我曾经的怀疑。 事实证明,Delphi7的UTF-8编码和JAVA的UTF-8编码是一致...

    SAS EG导入UTF-8编码的文本数据文件时的乱码问题解决方法

    UTF-8编码的文本文件在处理中文字符时,如果没有正确设置编码,可能会导致中文字符显示不正确,即出现乱码现象。SAS EG是一个图形用户界面的程序,它提供了数据管理、统计分析、报告创建等功能,但它在处理不同编码...

    IDEA支持带BOM的UTF-8编码文件.rar

    在大多数情况下,BOM在UTF-8编码中并不必要,因为它默认是小端序,但对于某些程序或系统,BOM可能有助于识别文件的编码方式。 在处理带BOM的UTF-8文件时,IDEA提供了很好的兼容性。通常,BOM可能会导致一些编辑器或...

    批量将文件编码方式由ansi转为utf-8

    这通常是由于ANSI编码不支持某些非英文字符,或者在跨平台交互时可能会遇到问题,而UTF-8编码则具有更广泛的支持和兼容性。 描述中提到"方便快速,转换速度快并且无错误,容易操作",这意味着所使用的工具或方法...

    source insight 3.5 UTF-8中文乱码插件_sourceinsight3.5_utf-8_插件补丁_中文乱码_

    总的来说,"source insight 3.5 UTF-8中文乱码插件"是解决Source Insight 3.5与UTF-8编码不兼容问题的有效工具,通过正确安装和应用此插件,开发者可以更顺畅地在Source Insight环境中阅读和编辑包含中文字符的代码...

    易语言UTF-8编码转换工具

    易语言UTF-8编码转换工具源码的分享,对学习易语言的初学者来说,是一个很好的实践案例,可以了解如何操作文件、读取和写入数据以及处理字符编码问题。 在处理编码转换时,通常会涉及到以下几个关键知识点: 1. **...

    utf-8码转换器(转换成utf-8码)

    UTF-8编码是一种广泛使用的字符编码标准,它能够表示Unicode字符集中的所有字符。这个“utf-8码转换器”程序是用SWT(Standard Widget Toolkit)开发的,旨在帮助用户将非UTF-8编码的文本转换为UTF-8编码。在IT行业...

    utf-8 ansi 字符互转 工具

    总结来说,理解和掌握UTF-8与ANSI字符编码的差异,以及如何进行转换,对于解决跨平台、多语言环境下的文本处理问题至关重要。在日常工作中,我们可以利用各种工具和编程手段,灵活应对不同编码格式带来的挑战。在...

    c++ UTF-8 UTF-16转换

    1. **编码不匹配**:如果输入的字符串不是有效的UTF-8或UTF-16编码,转换过程可能会失败。因此,转换前应先检查输入字符串的编码格式。 2. **内存管理**:转换可能会涉及内存分配和释放,确保正确处理可能导致内存...

    批量文件编码转换工具(Utf-8转GB2312、GB2312转Utf-8)

    本文将深入探讨批量文件编码转换工具,特别是“Utf-8转GB2312”与“GB2312转Utf-8”的转换过程,以及如何利用此类工具进行高效操作。 标题中的“批量文件编码转换工具”是指一种能够一次性处理大量文件,改变它们...

    utf-8 互转 gb2312 转码

    首先,我们需要将UTF-8编码的字符串解码为Unicode,然后将Unicode转换为GB2312编码。反之,从GB2312转到UTF-8也是同样的逻辑,只是方向相反。 在Python编程语言中,我们可以使用`encode()`和`decode()`方法进行转码...

    解决Invalid byte 1 of 1-byte UTF-8 sequence

    描述中提到的“Invalid byte 1 of 1-byte UTF-8 sequence”错误提示意味着在尝试解码一个UTF-8编码的字节序列时,遇到了一个无效的字节。这通常是因为文件或数据流被错误地识别为不同的字符集,如GBK,导致解码失败...

    java 中文字符串,utf-8编码为byte数组的计算过程

    你可以看到,对于“你好,世界”这个字符串,UTF-8编码的结果并不直接对应于每个字符的Unicode码点,而是根据UTF-8的编码规则组合字节。 此外,了解`unicode中文码表.xlsx`文件的作用也很重要。这个Excel表格很可能...

    中文转UTF-8编码

    具体来说,对于一个非ASCII的中文字符,UTF-8编码规则如下: - 对于Unicode范围在U+0080到U+07FF之间的字符,用两个字节表示。 - 对于Unicode范围在U+0800到U+FFFF之间的字符,用三个字节表示。 #### 四、示例代码...

Global site tag (gtag.js) - Google Analytics