`
apchy
  • 浏览: 61342 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

认识BOM

    博客分类:
  • java
 
阅读更多

什么是BOM

  BOM(byte-order mark),即字节顺序标记,它是插入到以UTF-8、UTF16或UTF-32编码Unicode文件开头的特殊标记,用来识别Unicode文件的编码类型。对于UTF-8来说,BOM并不是必须的,因为BOM用来标记多字节编码文件的编码类型和字节顺序(big-endian或little-endian)。 


 在绝大多数编辑器中都看不到BOM字符,因为它们能理解Unicode,去掉了读取器看不到的题头信息。若要查看某个Unicode文件是否以BOM开头,可以使用十六进制编辑器。下表列出了不同编码所对应的BOM。


BOM
  Encoding
  EF BB BF
  UTF-8
  FE FF
  UTF-16 (big-endian)
  FF FE
  UTF-16 (little-endian)
  00 00 FE FF
  UTF-32 (big-endian)
  FF FE 00 00
  UTF-32 (little-endian)

BOM的来历

  为了识别 Unicode 文件,Microsoft 建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符开头。这作为一个“特征符”或“字节顺序标记(byte-order mark,BOM)”来识别文件中使用的编码和字节顺序。

  不同的系统对BOM的支持

  因为一些系统或程序不支持BOM,因此带有BOM的Unicode文件有时会带来一些问题。

  1.        JDK1.5以及之前的Reader都不能处理带有BOM的UTF-8编码的文件,解析这种格式的xml文件时,会抛出异常:Content is not allowed in prolog.

  2.        Linux/UNIX 并没有使用 BOM,因为它会破坏现有的 ASCII 文件的语法约定。

  不同的编辑工具对BOM的处理也各不相同。使用Windows自带的记事本将文件保存为UTF-8编码的时候,记事本会自动在文件开头插入BOM(虽然BOM对UTF-8来说并不是必须的),但是editplus就不会这样做。

  BOM与XML

  XML解析读取XML文档时,W3C定义了3条规则:

  1.        如果文档中有BOM,就定义了文件编码;

  2.        如果文档中没有BOM,就查看XML声明中的编码属性;

  3.        如果上述两者都没有,就假定XML文档采用UTF-8编码。



java处理这类文件可参照老外的博文http://koti.mbnet.fi/akini/java/unicodereader/

主要有个处理类,如下,好东西呀 

UnicodeInputStream.java


/**
version: 1.1 / 2007-01-25
- changed BOM recognition ordering (longer boms first)

Original pseudocode   : Thomas Weidenfeller
Implementation tweaked: Aki Nieminen

http://www.unicode.org/unicode/faq/utf_bom.html
BOMs in byte length ordering:
   00 00 FE FF    = UTF-32, big-endian
   FF FE 00 00    = UTF-32, little-endian
   EF BB BF       = UTF-8,
   FE FF          = UTF-16, big-endian
   FF FE          = UTF-16, little-endian

Win2k Notepad:
   Unicode format = UTF-16LE
***/

import java.io.*;

/**
* This inputstream will recognize unicode BOM marks
* and will skip bytes if getEncoding() method is called
* before any of the read(...) methods.
*
* Usage pattern:
     String enc = "ISO-8859-1"; // or NULL to use systemdefault
     FileInputStream fis = new FileInputStream(file);
     UnicodeInputStream uin = new UnicodeInputStream(fis, enc);
     enc = uin.getEncoding(); // check and skip possible BOM bytes
     InputStreamReader in;
     if (enc == null) in = new InputStreamReader(uin);
     else in = new InputStreamReader(uin, enc);
*/
public class UnicodeInputStream extends InputStream {
   PushbackInputStream internalIn;
   boolean             isInited = false;
String              defaultEnc;
String              encoding;

private static final int BOM_SIZE = 4;

UnicodeInputStream(InputStream in, String defaultEnc) {
internalIn = new PushbackInputStream(in, BOM_SIZE);
this.defaultEnc = defaultEnc;
}

public String getDefaultEncoding() {
      return defaultEnc;
   }

   public String getEncoding() {
      if (!isInited) {
         try {
            init();
         } catch (IOException ex) {
            IllegalStateException ise = new IllegalStateException("Init method failed.");
            ise.initCause(ise);
            throw ise;
         }
      }
      return encoding;
   }

   /**
    * Read-ahead four bytes and check for BOM marks. Extra bytes are
    * unread back to the stream, only BOM bytes are skipped.
    */
   protected void init() throws IOException {
      if (isInited) return;

      byte bom[] = new byte[BOM_SIZE];
      int n, unread;
      n = internalIn.read(bom, 0, bom.length);

      if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) &&
                  (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) {
         encoding = "UTF-32BE";
         unread = n - 4;
      } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) &&
                  (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) {
         encoding = "UTF-32LE";
         unread = n - 4;
      } else if (  (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) &&
            (bom[2] == (byte)0xBF) ) {
         encoding = "UTF-8";
         unread = n - 3;
      } else if ( (bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF) ) {
         encoding = "UTF-16BE";
         unread = n - 2;
      } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) ) {
         encoding = "UTF-16LE";
         unread = n - 2;
      } else {
         // Unicode BOM mark not found, unread all bytes
         encoding = defaultEnc;
         unread = n;
      }     
      //System.out.println("read=" + n + ", unread=" + unread);

      if (unread > 0) internalIn.unread(bom, (n - unread), unread);

      isInited = true;
   }

   public void close() throws IOException {
      //init();
      isInited = true;
      internalIn.close();
   }

   public int read() throws IOException {
      //init();
      isInited = true;
      return internalIn.read();
   }
}
UnicodeReader.java
/**
version: 1.1 / 2007-01-25
- changed BOM recognition ordering (longer boms first)

Original pseudocode   : Thomas Weidenfeller
Implementation tweaked: Aki Nieminen

http://www.unicode.org/unicode/faq/utf_bom.html
BOMs:
   00 00 FE FF    = UTF-32, big-endian
   FF FE 00 00    = UTF-32, little-endian
   EF BB BF       = UTF-8,
   FE FF          = UTF-16, big-endian
   FF FE          = UTF-16, little-endian

Win2k Notepad:
   Unicode format = UTF-16LE
***/

import java.io.*;

/**
* Generic unicode textreader, which will use BOM mark
* to identify the encoding to be used. If BOM is not found
* then use a given default or system encoding.
*/
public class UnicodeReader extends Reader {
   PushbackInputStream internalIn;
   InputStreamReader   internalIn2 = null;
   String              defaultEnc;

   private static final int BOM_SIZE = 4;

   /**
    *
    * @param in  inputstream to be read
    * @param defaultEnc default encoding if stream does not have
    *                   BOM marker. Give NULL to use system-level default.
    */
   UnicodeReader(InputStream in, String defaultEnc) {
      internalIn = new PushbackInputStream(in, BOM_SIZE);
      this.defaultEnc = defaultEnc;
   }

   public String getDefaultEncoding() {
      return defaultEnc;
   }

   /**
    * Get stream encoding or NULL if stream is uninitialized.
    * Call init() or read() method to initialize it.
    */
   public String getEncoding() {
      if (internalIn2 == null) return null;
      return internalIn2.getEncoding();
   }

   /**
    * Read-ahead four bytes and check for BOM marks. Extra bytes are
    * unread back to the stream, only BOM bytes are skipped.
    */
   protected void init() throws IOException {
      if (internalIn2 != null) return;

      String encoding;
      byte bom[] = new byte[BOM_SIZE];
      int n, unread;
      n = internalIn.read(bom, 0, bom.length);

      if ( (bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) &&
                  (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF) ) {
         encoding = "UTF-32BE";
         unread = n - 4;
      } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) &&
                  (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00) ) {
         encoding = "UTF-32LE";
         unread = n - 4;
      } else if (  (bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) &&
            (bom[2] == (byte)0xBF) ) {
         encoding = "UTF-8";
         unread = n - 3;
      } else if ( (bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF) ) {
         encoding = "UTF-16BE";
         unread = n - 2;
      } else if ( (bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) ) {
         encoding = "UTF-16LE";
         unread = n - 2;
      } else {
         // Unicode BOM mark not found, unread all bytes
         encoding = defaultEnc;
         unread = n;
      }   
      //System.out.println("read=" + n + ", unread=" + unread);

      if (unread > 0) internalIn.unread(bom, (n - unread), unread);

      // Use given encoding
      if (encoding == null) {
         internalIn2 = new InputStreamReader(internalIn);
      } else {
         internalIn2 = new InputStreamReader(internalIn, encoding);
      }
   }

   public void close() throws IOException {
      init();
      internalIn2.close();
   }

   public int read(char[] cbuf, int off, int len) throws IOException {
      init();
      return internalIn2.read(cbuf, off, len);
   }

}

 

分享到:
评论
1 楼 lizhou 2012-08-21  
周sir玩的深啊

相关推荐

    Web前端开发技术-认识BOM对象.pptx

    在Web前端开发中,BOM(Browser Object Model)和DOM(Document Object Model)是两个非常重要的概念。DOM主要处理HTML或XML文档结构,允许开发者通过JavaScript来操纵文档内容、结构和样式。而BOM则是专注于浏览器...

    bom基础知识-教你如何建立BOM

    通过以上五个章节的学习,你应该对BOM有了更全面的认识,掌握了创建BOM的基本方法和注意事项。在实际工作中,结合合适的BOM管理系统,你将能够更高效地管理产品生命周期中的各个阶段。不断实践和优化,BOM将成为你手...

    BOM说明常见几种BOM

    BOM 管理是企业技术管理信息化的主要内容,但许多企业对 BOM 的认识不够,有些企业甚至在选型中连 BOM 是何含义都不理解。 因此,本文对 BOM 的定义、分类、应用进行了详细的介绍。 一、BOM 的定义 BOM 是一种...

    BOM表制作说明

    BOM表了解和认识 是初学者认识什么是bom表格 他的定义与内容要素

    Bom Claim平台上线指南:高效零成本数字资产管理与收益教程

    使用场景及目标:用户可以在无广告干扰环境下,利用Bom Claim提供的工具和服务管理多个区块链资产,通过日常任务累积加密货币收入,提高对数字货币的认识和技术掌握程度。 其他说明:文中提到的特定日期(如2024年...

    3米冷却定型台(sw18可编辑+工程图+bom).rar

    《3米冷却定型台(SW18可...通过深入学习和理解这个压缩包内的内容,不仅可以提升机械设计和工程实践能力,还能对项目管理和供应链运作有更全面的认识。对于从事或有意进入相关领域的学习者而言,这是一份宝贵的资源。

    ATMEGA8L单片机非常好的学习资料有原理图+源代码+BOM+仿真+其它技术资料.7z

    理解了原理图,就能对整个电路的工作原理有一个直观的认识,包括电源如何供给、各端口如何分配、时钟如何生成以及复位功能如何实现等。此外,原理图还是仿真和电路板设计的前提,对于初学者而言,通过研究原理图可以...

    产品架构认识.pptx

    这份名为"产品架构认识.pptx"的文件主要讲解了与产品架构相关的一些关键知识点,包括物料管理、工程变更控制以及如何通过特定系统查询产品相关信息。 1. **Bill Of Material (BOM)**: BOM是一个详细列出产品所有...

    基于SpringBoot+Vue的BOM表智能生成系统设计与实现.docx

    本文主要探讨了一款基于SpringBoot和Vue的BOM(Bill of Materials)表智能生成系统的设计与实现,这对于理解和掌握这...通过阅读和理解这篇论文,学习者能够对这两种技术有更深入的认识,并能将其应用于自己的项目中。

    物料清单(BOM)驳回的常见原因及避免方法_中文电子书-综合文档

    5. **培训与沟通**:定期对相关人员进行BOM管理培训,提高他们对BOM重要性的认识,并加强团队间的沟通。 6. **实施变更控制**:当有设计变更时,应遵循严格的变更控制流程,包括评估影响、通知相关方并更新所有相关...

    移动印刷机(sw可编辑+工程图+BOM)_零件图_机械工程图_机械三维3D设计图打包下载.zip

    无论是初学者还是资深工程师,都可以通过这份资料深化对机械工程的认识,提升设计能力,并且可能激发出创新的设计思路。对于教育领域而言,这是一份不可多得的实践教学资料,它不仅能够辅助学生和教师进行教学活动,...

    对产品架构的认识.pptx

    - **产品结构认识**:查看产品结构表,了解产品的层次结构和组件关系。 - **料件适用机种查询**:查找某个组件适用于哪些机型,有助于优化库存管理和供应链管理。 - **单阶材料用量明细表查询**:获取特定主件料号的...

    产品架构认识(4).pptx

    这份名为"产品架构认识(4).pptx"的文件主要涵盖了产品开发过程中的物料管理、工程变更流程以及相关查询操作,对于理解产品生命周期管理和生产流程具有重要意义。 首先,我们来看物料管理的部分。Bill Of Material...

    对UTF8编码的初步认识.rar_UTF8_utf

    通过学习这个网页,我们可以深入理解UTF8的工作机制,比如字节顺序标记(BOM)、编码规则以及如何识别和处理多字节序列。 另一方面,“www.pudn.com.txt”可能是一个包含示例文本的文件,这些文本可能是使用UTF8...

    产品研发数据工程师培训.pdf

    1. 产品数据管理模式的认识:课程通过案例分析,帮助学员理解产品数据在研发、供应链、销售和服务等环节的重要性,以及如何通过良好的产品数据管理策略来规划和实施企业的发展。 2. 版本管理:学员将学习PART(零...

    Web前端开发技术-认识DOM对象.pptx

    【Web前端开发技术-认识DOM对象】 在Web前端开发中,DOM(Document Object Model)对象是至关重要的概念,它是一个标准的编程接口,允许开发者通过JavaScript等脚本语言操作HTML和XML文档。DOM将HTML或XML文档解析...

    NXP LPC51U68 的有线机械键盘BOM-综合文档

    通过这份BOM文档,可以对一个有线机械键盘设计所涉及的电子元件、微控制器以及其间的连接关系有一个全面的认识。这些信息对于电子工程师在进行电路设计、组装、故障排除以及后续维护中至关重要。

    缺少的维护工具 和 MRO 库存控制.pdf

    行业内的领军企业已经认识到BOM的重要性,并将其作为实现成本节约、提高运营效率的关键策略之一。这些公司通常设定明确的目标来优化其MRO库存管理流程,包括但不限于: - **减少库存水平**:通过准确预测需求并减少...

    制造业跨工厂物料成本估算方法与步骤解析

    文中不仅提供了具体操作路径指导还涉及一些基本概念如物料主数据查找、BOM(Bill of Materials)结构的展示、数量结构和成本结果展示等。这使得读者能够对物料从源头采购到最后的成本构成有一个系统而清晰的认识。

    《MRP与CIMS》实验报告书.docx

    通过这样的实验报告书,学生可以将课堂上学习到的理论知识与实践操作紧密结合,从而在制造业信息化管理领域中取得更深入的认识和更高的操作技能。实验报告书不仅是对学生学习成果的一次重要检验,也为他们将来在制造...

Global site tag (gtag.js) - Google Analytics