`
天使的左手
  • 浏览: 55588 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

跳过UTF-8的BOM

    博客分类:
  • 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
***/

public class UnicodeInputStream extends InputStream
{
    public static void main(String[] args) throws Exception
    {
        UnicodeInputStream ui = new UnicodeInputStream(new FileInputStream("data.txt"), "UTF-8");
        CharBuffer cb = CharBuffer.allocate(10);
        String encoding = ui.getEncoding();
        System.out.println(encoding);
        InputStreamReader reader = new InputStreamReader(ui, encoding);
        int len = 0;
        while((len = reader.read(cb)) != -1) {
            cb.flip();
            System.out.print("===" + cb + "===");
            cb.clear();
        }
        reader.close();
    }
    
    private PushbackInputStream internalIn;
    private boolean isInited = false;
    private String defaultEnc;
    private String encoding;
    private static final int BOM_SIZE = 4;

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

    void init() throws IOException
    {
        if (isInited)
            return;
        byte[] bom = new byte[BOM_SIZE];
        int n = internalIn.read(bom, 0, bom.length);
        int skip;
        
        if ((bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) && (bom[2] == (byte)0xFE) && (bom[3] == (byte)0xFF))
        {
            skip = 4;
            encoding = "UTF-32BE";
        }
        else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) && (bom[2] == (byte)0x00) && (bom[3] == (byte)0x00))
        {
            skip = 4;
            encoding = "UTF-32LE";
        }
        else if ((bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) && (bom[2] == (byte)0xBF))
        {
            skip = 3;
            encoding = "UTF-8";
        }
        else if ((bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF))
        {
            skip = 2;
            encoding = "UTF-16BE";
        }
        else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE))
        {
            skip = 2;
            encoding = "UTF-16LE";
        }
        else
        {
            skip = 0;
            encoding = defaultEnc;
        }

        if(n != -1)
            internalIn.unread(bom, skip, n - skip);
        isInited = true;
    }

    public String getEncoding()
    {
        try
        {
            init();
        }
        catch (IOException e)
        {
            throw new IllegalStateException(e);
        }
        return encoding;
    }

    public String getDefaultEncoding()
    {
        return defaultEnc;
    }

    @Override
    public int read() throws IOException
    {
        return internalIn.read();
    }

    @Override
    public void close() throws IOException
    {
        internalIn.close();
    }
}



public class UnicodeReader extends Reader
{
    public static void main(String[] args) throws Exception
    {
        UnicodeReader reader = new UnicodeReader(new FileInputStream("data.txt"), "UTF-8");
//        CharBuffer cb = CharBuffer.allocate(10);
//        System.out.println(reader.getEncoding());
//        int len = 0;
//        while ((len = reader.read(cb)) != -1)
//        {
//            cb.flip();
//            System.out.print("===" + cb + "===");
//            cb.clear();
//        }
//        reader.close();
        
        BufferedReader br = new BufferedReader(reader);
        String line;
        while((line = br.readLine()) != null)
            System.out.println(line);
        br.close();
    }

    private static final int BOM_SIZE = 4;
    private PushbackInputStream internalIn;
    private InputStreamReader reader;
    private String encoding;
    private String defaultEnc;
    private boolean isInited = false;

    public UnicodeReader(InputStream in, String defaultEncoding)
    {
        defaultEnc = defaultEncoding;
        internalIn = new PushbackInputStream(in, BOM_SIZE);
        try
        {
            init();
            reader = new InputStreamReader(internalIn, encoding);
        }
        catch (IOException e)
        {
            try
            {
                internalIn.close();
            }
            catch (IOException e1)
            {
                e1.printStackTrace();
            }

            throw new ExceptionInInitializerError("initialization failed");
        }
    }

    public String getEncoding()
    {
        return encoding;
    }

    protected void init() throws IOException
    {
        if (isInited)
            return;
        byte[] bom = new byte[BOM_SIZE];
        int n = internalIn.read(bom, 0, bom.length), skip;

        if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF))
        {
            skip = 4;
            encoding = "UTF-32BE";
        }
        else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00))
        {
            skip = 4;
            encoding = "UTF-32LE";
        }
        else if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF))
        {
            skip = 3;
            encoding = "UTF-8";
        }
        else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF))
        {
            skip = 2;
            encoding = "UTF-16BE";
        }
        else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE))
        {
            skip = 2;
            encoding = "UTF-16LE";
        }
        else
        {
            skip = 0;
            encoding = defaultEnc;
        }

        if (n != -1)
            internalIn.unread(bom, skip, n - skip);
        isInited = true;
    }

    @Override
    public void close() throws IOException
    {
        reader.close();
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException
    {
        return reader.read(cbuf, off, len);
    }
}


参考
http://koti.mbnet.fi/akini/java/unicodereader/
分享到:
评论

相关推荐

    Java解决UTF-8的BOM问题

    总之,Java处理UTF-8的BOM问题主要是通过自定义读取器或者使用第三方库,如Apache Commons IO的`TidyCharsets`类,来检测并跳过BOM字节。这样可以确保程序正确地解析和处理带有BOM的UTF-8文本文件,避免出现乱码或者...

    utf-8批量bom添加删除(BomChecker)工具

    1.首先介绍一下本人应用场景,qt...3.此小工具主要针对utf-8编码文件,能够批量添加删除BOM,无识别转化ASIIC功能,添加BOM时,如果文件是utf-8(BOM),则跳过,删除亦然 4.当不选中添加删除时可用于文件数量统计。

    java 读取服务器上的某个文件,并解决UTF-8 BOM文件的问号问题

    这个场景中,我们面临的挑战是如何正确处理UTF-8带有BOM(Byte Order Mark)的文件,因为BOM可能会导致文件内容显示为问号或者其他乱码。下面将详细介绍如何解决这个问题。 首先,我们需要理解什么是UTF-8的BOM。...

    此文件用于快速反查php文件中的UTF8编码的文件是不是加了BOM,有则显示,无则跳过。(php源码)。

    如何解决BOM:先放在服务器可执行目录下,使用 浏览器http://服务器ip/存放路径/bom.php来 访问,填写实际路径执行后可得到存在有BOM的PHP文件,然后再用notepad++打开,在菜单选“格式”->“转为UTF-8无BOM..”即可. ...

    MFC读取utf8示例

    函数接受一个文件路径作为参数,然后打开文件,跳过可能存在的BOM(UTF-8的BOM是三个字节:0xEF, 0xBB, 0xBF),逐行读取内容并使用`AfxMessageBox`显示。注意,由于`AfxMessageBox`处理的是宽字符字符串,所以在...

    PHP批量删除、清除UTF-8文件BOM头的代码实例

    在处理文本数据时,尤其是从不同的系统或编辑器导出的文本文件,我们可能会遇到一个问题,那就是文件可能包含UTF-8编码的字节顺序标记(Byte Order Mark,简称BOM)。BOM通常用于UTF-16和UTF-32编码的文件中来标识...

    批量移除文件的BOM格式

    这个程序会遍历指定目录及其子目录中的所有文件,如果文件以UTF-8 BOM开头,它将读取文件的前三个字节(即BOM),然后跳过它们并写入剩余的数据。这样,BOM就被有效地移除了。 需要注意的是,这个方法只适用于文件...

    java去掉txt文本的bom头信息

    BOM是Unicode编码格式中的一个特殊字符,用于标识文件的编码类型,常见于UTF-8、UTF-16和UTF-32等格式。在某些情况下,如读取或合并多个文本文件时,BOM头可能会导致不必要的困扰,例如乱码或解析错误。本文将详细...

    C#获取去除文件bom头后的内容

    在UTF-8编码中,BOM是一个特殊的字节序列`FF FE`,用以表明该文件是UTF-8编码。然而,在某些情况下,BOM头可能会导致乱码问题,尤其是当程序不期望或无法正确处理这个额外字节序列时。本文将详细介绍如何使用C#语言...

    PHP遍历文件夹与文件类及处理类用法实例__2.docx

    `check_utf8bom` 方法用来检测文件是否存在 UTF-8 BOM。它读取文件的前三个字节,与 BOM 的字节序列 `0xEF 0xBB 0xBF` 进行比较。如果匹配,则返回 `true`,否则返回 `false`。 `clear_utf8bom` 方法则负责清除文件...

    PHP遍历文件夹与文件类及处理类用法实例__1.docx

    `check_utf8bom()` 方法检查文件的前三个字节是否为 UTF-8 BOM 的字节序列(0xEF 0xBB 0xBF),如果是则返回 true。 `clear_utf8bom()` 方法负责清除文件的 BOM。通常,这个操作会打开文件,读取前三个字节,然后跳...

    php去除BOM文档的函数类

    此外,这个函数只适用于UTF-8编码的文件,对于其他编码格式的BOM,可能需要使用不同的方法。 这个函数类的使用非常简单,只需要实例化`BOMRemover`对象,然后调用`removeBOM`方法即可: ```php $bomRemover = new ...

    检测BOM并根据需要删除-Golang开发

    utfbom软件包utfbom实现了BOM(Unicode字节顺序标记)的检测并根据需要删除。... byte(” hello“))} func trySkip(byteData [] byte){fmt.Println(” Input:“,byteData)//仅跳过BOM outpu

    微信小程序开发-创建版本库.pptx

    在Windows系统中,需要注意文件的编码问题,特别是使用文本编辑器时,应避免使用Windows自带的记事本,因为它在保存UTF-8编码的文件时会添加BOM头,可能导致各种问题。推荐使用Notepad++这样的第三方编辑器,并设置...

    批量编码转化工具(实现文件编码的自动检测)

    BOM是某些编码(如UTF-16和UTF-8)在文件开头放置的一个特殊标记,用于表明其编码类型。而统计字符频率和比较编码表则是通过分析文件中的字符出现的频率,与已知编码的字符频率分布进行对比,以判断最可能的编码类型...

    php写入txt乱码的解决方法

    可能你会先尝试从编码入手尝试解决,但最终的...在Windows下用记事本之类的程序将文本文件保存为UTF-8格式时,记事本会在文件头前面加上几个不可见的字符(EF BB BF),就是所谓的BOM(Byte order Mark)。 不仅限于

    java读取文件:char的ASCII码值=65279,显示是一个空字符的解决

    这个字符被称为Unicode的Byte Order Mark (BOM),它被用作UTF-8、UTF-16等编码方式的标识符,用来指示文件的字节顺序。在某些情况下,BOM并不会被正确处理,导致程序行为异常,例如在上述描述中的字符串比较问题。 ...

    PHP自动识别字符集并完成转码详解

    文章中还提到,对于文件的检查与转码,可以检查UTF-8的BOM(Byte Order Mark,字节顺序标记)信息,这是UTF-8编码文件的一个特性,用于标识该文件是使用UTF-8编码。TP工具箱的编码转换功能就是一个实际应用的例证,...

    检查php文件中是否含有bom的函数

    常见的UTF-8编码的文件可能会在开头包含0xEF,0xBB,0xBF这三个字节,这就是UTF-8编码文件的BOM。 2. PHP文件中BOM的影响:在PHP文件中,如果存在BOM,特别是当服务器不正确处理BOM时,可能会导致语法解析错误,出现...

    php 读取txt文档分页显示

    但是,如果遇到BOM头(UTF-8 Byte Order Mark),可能需要先跳过: ```php if (substr($content, 0, 3) === "\xEF\xBB\xBF") { $content = substr($content, 3); } ``` 4. **分页显示**: 为了实现分页,我们...

Global site tag (gtag.js) - Google Analytics