Java读取Unicode文件(UTF-8等)时碰到的BOM首字符问题

摘要:
如果选择以Unicode格式(如UTF-8)保存在Windows下使用文本编辑器创建的文本文件,则BOM表标识符将添加到文件头。当Java读取文件和字符串时,不会删除此标识符。无法删除trim()。幸运的是,当Java读取Unicode文件时,它会将BOM更改为“uFEFF”。通过这种方式,可以手动解决:[java]viewplatecopyif{//line=line.substring;line=line.replace;}然而,这种方法并不完美。如果生成的jar文件在Windows下运行,则仍然存在问题。BOM=ByteOrderMarkBOM是Unicode规范中推荐的标记字节顺序的方法。UTF-8不需要BOM来指示字节顺序,但可以使用BOM来指示“我是UTF-8编码的”。
在Windows下用文本编辑器创建的文本文件,如果选择以UTF-8等Unicode格式保存,会在文件头(第一个字符)加入一个BOM标识。
 
这个标识在Java读取文件的时候,不会被去掉,而且String.trim()也无法删除。如果用readLine()读取第一行存进String里面,这个String的length会比看到的大1,而且第一个字符就是这个BOM。
 
这种情况会造成一些麻烦,比如在读取ini文件的时候,如果想判断第一行是不是以“[”开头就无法正确判断。
 
幸好,Java在读取Unicode文件的时候,会统一把BOM变成“uFEFF”,这样的话,就可以自己手动解决了(判断后,用substring()或replace()去除掉这个BOM):
[java] view plain copy
 
  1. if(line.startsWith("uFEFF")){  
  2.  //line = line.substring(1);  
  3.  line = line.replace("uFEFF", "");  
  4. }  
 
然而,这种方法并不是完美的,如果生成jar文件在windows下运行,还是有问题。终极的解决方法是使用apache commons io提供的BOMInputStream:
[html] view plain copy
 
  1. <dependency>  
  2.     <groupId>commons-io</groupId>  
  3.     <artifactId>commons-io</artifactId>  
  4.     <version>2.4</version>  
  5. </dependency>  

[java] view plain copy
 
  1. BufferedReader reader = null;  
  2.        try {  
  3.            //reader = new BufferedReader(new FileReader(file));  
  4.           
  5.         //使用BOMInputStream自动去除UTF-8中的BOM!!!  
  6.         reader = new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream(file))));  
  7.   
  8.         String str = null;  
  9.            //一次读入一行(非空),直到读入null为文件结束  
  10.            while ((str = reader.readLine()) != null) {  
  11.            }  
 
什么是BOM?
BOM = Byte Order Mark
BOM是Unicode规范中推荐的标记字节顺序的方法。比如说对于UTF-16,如果接收者收到的BOM是FEFF,表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明“我是UTF-8编码”。BOM的UTF-8编码是EF BB BF(用UltraEdit打开文本、切换到16进制可以看到)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
 
所有的BOM在C/C++/Java中都被处理为"uFEFF"(???貌似不一定。。。),参考:http://www.fileformat.info/info/unicode/char/feff/index.htm
 
Wikipedia关于POM的说明介绍:
https://en.wikipedia.org/wiki/Byte_order_mark
 
转载自Clement-Xu的csdn博客。 https://blog.csdn.net/ClementAD/article/details/47168573

免责声明:文章转载自《Java读取Unicode文件(UTF-8等)时碰到的BOM首字符问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Sql Server 游标使用 demo配置nginx 反向代理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Firefox浏览器设置字符编码格式

今天写博客,敲示例代码时遇到的问题。简单的HTML页面,在火狐浏览器出现中文乱码。如果是IE浏览器的话,直接通过菜单查看 –> 编码 就可以指定编码方式,解决乱码问题。现在Firefox浏览器版本升级太快,且展示方式也经常变化,本人还找了一番才找到火狐浏览器的设置字符编码的方式,在此分享出来,希望能帮到碰到这个问题的朋友。 本人使用的Firefo...

shell脚本(3)-格式化输出

一个程序需要有0个或以上的输入,一个或更多输出 一、echo语法 1、功能:将内容输出到默认显示设备。 echo命令功能在显示器上显示一段文字,一般提到提示的作用 2、语法:echo[-ne][字符串] 补充说明:echo会将输入的字符串送往标准输出,输出的字符串以空白字符隔开,并在最后加上换行号。 命令选项: -n:不在最后自动换行: [root@loc...

详解centos下vi的用法

     vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令。由于对Unix及Linux系统的任何版本,vi编辑器是完全相同的,因此您可以在其他任何介绍vi的地方进一步了解它。Vi也是Linux中最基本的文本编辑器,学会它后,您将在Linux的世界里畅行无阻。 1、vi...

Oracle 和SQL Server 中的SQL语句使用区别

最近开始接触Oracle,想要了解下同SQL Server使用时的区别。搜寻网上信息找到具体区别分类如下: 一、数据类型比较  类型名称 Oracle  SQLServer  比较  字符数据类型  CHAR  CHAR  都是固定长度字符资料但oracle里面最大度为2kb,SQLServer里面最大长度为8kb  变长字符数据类型  VAR...

Linux下修改MySQL数据库字符编码为UTF-8解决中文乱码

由于MySQL编码原因会导致数据库出现乱码。 解决办法: 修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家需要用到的字符,是国际编码。 具体操作: 1、进入MySQL控制台 >mysql -uroot -p #输入密码进入 >status; #查看当前MySQL运行状态,如下图所示:  ...

【转】宽字节注入详解

前言在mysql中,用于转义的函数有addslashes,mysql_real_escape_string,mysql_escape_string等,还有一种情况是magic_quote_gpc,不过高版本的PHP将去除这个特性。 首先,宽字节注入与HTML页面编码是无关的,笔者曾经看到 &lt;meta charset=utf8&gt;...