`

Java根据文件的BOM判断文件的编码类型

阅读更多
    随着多字节文本数据的处理,尤其是非ASCII文字的出现,典型的如中文,文件的编码判断就提上日程,有很多字节流和字符流默认能处理的编码格式的是和程序文件的编码一致,例如:程序文件编码是UTF-8,默认处理的文本也是UTF-8。处理其他格式的文本时,当不提供具体的编码时,就非常容易把其他格式的文本当成乱码处理。

        当前处理的方式一般通过相关reader或writer的装饰类:
InputStreamReader(InputStream in, String charsetName) 
OutputStreamWriter(OutputStream out, String charsetName) 
 
         实现显示地将字符编码传进去,但是无法实现自动的发掘文件字符编码,也就是说,此种模式仅仅支持用户将文件的编码传进去。

    对中文字符编码主要是GBK(GB2312,GB18030)系列和UTF系列的区别,UTF系列的编码通常在文件的头部若干个字节已经告诉用户此文件的字符编码格式,即文件包含BOM(Byte Order Mark),此标志标志文件的编码方式,常见的有:

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


    在此处提供两个输入流方法,一种是基于字符的reader:
/**
 * 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
 *
 * @author Semantic Wang
 * 
 */
public class UnicodeReader extends Reader{

	PushbackInputStream pbin;
	InputStreamReader reader = null;
	String defaultEnc;

	private static final int BOM_SIZE = 4;
	
	
	/**
	 * 
	 * @param in
	 *            inputstream to be read
	 * 
	 */
	public UnicodeReader(InputStream in) {
		this(in, "GBK");
	}
	
	/**
	 * 
	 * @param in
	 *            inputstream to be read
	 * @param defaultEnc
	 *            default encoding if stream does not have BOM marker. Give NULL
	 *            to use system-level default.
	 */
	public UnicodeReader(InputStream in, String defaultEnc) {
		pbin = 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 (reader == null)
			return null;
		return reader.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 (reader != null)
			return;

		String encoding;
		byte bom[] = new byte[BOM_SIZE];
		int n, unread;
		n = pbin.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)
			pbin.unread(bom, (n - unread), unread);

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

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

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

}

另一种是基于字节的输入流InputStream:

/**
 * @author Semantic Wang
 * 
 */
public class UnicodeInputStream extends InputStream {

	PushbackInputStream pbin;
	boolean isInited = false;
	String defaultEnc;
	String encoding;

	private static final int BOM_SIZE = 4;
	
	public UnicodeInputStream(InputStream in) {
		this(in, "GBK");
	}

	public UnicodeInputStream(InputStream in, String defaultEnc) {
		pbin = 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 = pbin.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)
			pbin.unread(bom, (n - unread), unread);

		isInited = true;
	}

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

	public int read() throws IOException {
		// init();
		isInited = true;
		return pbin.read();
	}

}


    最后的调用方式为:
InputStream in = new FileInputStream(fileName);
BufferedReader reader = new BufferedReader(new UnicodeReader(in));
分享到:
评论

相关推荐

    java获取文件编码(判断有无BOM)

    本文将详细介绍如何在Java中获取文件的编码并判断文件是否带有BOM。 首先,让我们了解一下什么是BOM。BOM是UTF-8、UTF-16和UTF-32等编码格式中的一个可选标记,用于告知解析器文件的编码类型。例如,UTF-8的BOM是三...

    Java判断文件编码格式 - 明明是悟空 - 博客园1

    在Java编程中,判断文件编码格式是一项常见的任务,特别是在处理包含多国语言或者用户自定义内容的文件时。本文将探讨如何使用Java进行文件编码格式的识别,主要介绍两种方法:一种是简单的UTF-8判断,另一种是使用...

    Java判断文件的编码

    判断文件编码的基本方法是读取文件的前几个字节,根据这些字节的特征来确定文件的编码类型。对于UTF-8、UTF-16等常见编码格式,可以通过检查特定的字节序列来实现快速识别。 #### 示例代码分析 下面是一段用于判断...

    java程序判断文件编码的类型

    ### Java程序判断文件编码的类型 #### 知识点概览 本文档旨在教导读者如何通过Java编程语言来判断文件的编码类型。这包括常见的编码格式如GBK、UTF-8等。了解文件编码对于处理多语言环境下的文本数据至关重要。 ##...

    java判断编码方式

    总之,Java中判断文件编码的方式多样,可以根据具体场景选择合适的方法。需要注意的是,这些方法都有其局限性,特别是对于没有BOM且包含混合字符集的文件,可能会比较困难。因此,最好的实践是在创建文件或数据时就...

    java判断文件编码

    在Java编程中,判断文件编码是一项重要的任务,尤其是在处理用户上传的文件或处理不同系统间的文件传输时。本文将深入探讨如何使用Java进行文件编码的检测,并基于提供的资源——`cpdetector_1.0.5.jar`、`chardet....

    java判断文件编码或文本流编码的方法宣贯.pdf

    以下将详细介绍如何在Java中进行文件编码的判断。 首先,基本的判断方法是通过读取文件的前三个字节来识别编码格式。ASCII码文本通常不涉及这个问题,因为ASCII只包含128个字符,可以用单字节表示。但对于非ASCII...

    读取创建CSV文件并自动解析文件编码方式

    在Java中,`java.nio.charset.Charset`类用于表示字符编码,但默认情况下,Java文件读取操作通常假设文件为UTF-8编码。对于其他编码,我们需要借助第三方库如`jcconf`或`ICU4J`来检测编码。 ```java import ...

    java识别文件编码格式

    一种常见的方法是逐行读取文件,尝试用多种常见编码进行解码,根据解码是否成功或解码后的字符集来判断文件的编码。 6. **错误计数法**:如果在读取文件时遇到乱码,可以通过记录错误字符的数量和类型来推测文件的...

    java获取字符串编码类型代码(导入直接查看结果)

    在Java编程语言中,处理字符串时,了解字符串的编码类型是非常重要的。编码类型决定了字符集,它定义了如何将字符转换为数字(字节)以及如何将数字转换回字符。常见的编码类型有ASCII、ISO-8859-1、UTF-8、GBK等。...

    判断文本文件是否为UTF-8编码

    在实际应用中,这种功能常用于编程语言的文本处理库,例如Python的`chardet`库,Java的`CharsetDetector`,或者C++的`ICU`库等,它们都提供了自动检测文件编码的方法。 了解并掌握文本文件的编码识别,对于进行跨...

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

    文件编码是用来表示文本字符的规则,常见的有ASCII、GB2312、GBK、UTF-8等。不同的编码方式决定了字符集的大小和覆盖的字符范围。例如,ASCII只包含英文字符,而GBK则包含了更多的中文字符。UTF-8是一种多字节编码...

    获取文件编码格式与文件转码

    - **使用工具库**:Java和Android中有多种库可以帮助我们检测文件编码,如`jChardet`、`ICU4J`等。它们利用统计学模型分析文件内容来猜测编码。 - **编程实现**:例如在Android中,可以自定义函数读取文件部分内容...

    自动编码识别 BOM

    通过读取文件头的字节并进行匹配,可以轻易判断出文件的编码类型。以下是一个简单的Java示例,演示如何检测UTF-8、UTF-16LE和UTF-16BE的BOM: ```java int p = (bin.read() ) + bin.read(); switch (p) { case 0...

    java读取文件免除乱码

    提供的`EncodingDetect.java`文件可能包含一个自定义的编码检测工具,通过分析文件头几个字节来判断文件的编码类型。这类方法通常基于字节序标记(BOM)或者特定编码的字符识别规则。例如,UTF-8编码的文件如果带有...

    java检测编码工具类

    Java编码检测工具类是Java开发中非常实用的一个组件,它能够帮助开发者准确地识别和处理各种文件的编码格式。在处理跨平台或者不同系统间的数据交换时,编码问题常常成为困扰,因为不同的操作系统和程序可能使用不同...

    Java 自动识别编码

    然而,Java标准库并没有提供一种直接的自动检测文件编码的方法。通常,开发者需要借助第三方库或者自定义算法来实现这个功能。 这篇名为“BytesEncodingDetect.java”的文件很可能包含了一个自定义的编码检测算法。...

    有关Java编码输出

    本篇文章将详细探讨如何在Java中判断文件编码,并根据不同的编码方式进行正确的输出。 #### 文件编码的判断与处理 在上述代码片段中,我们看到一个关于文件编码检测和输出的例子。主要涉及到以下几个关键步骤: 1...

    Java读取TXT文本文件乱码解决方案.pdf

    对于程序来说,可以读取文件的前几个字节,然后根据这些字节判断文件的编码类型。例如,可以编写一个工具函数来检测文件的编码: ```java public static String detectEncoding(File file) { // 读取文件前几个...

    挺好用的文件获取编码的工具类zip

    这个工具类可能包含了多个静态方法,用于检测不同类型的文件编码,并返回最有可能的编码结果。开发者可以通过调用这些方法,轻松地集成到自己的项目中,处理各种未知编码的文件。 例如,工具类可能包含一个名为`...

Global site tag (gtag.js) - Google Analytics