Java正确判别出文件的字符集(尤其是带BOM和不带BOM的UTF-8字符)
前几天在项目中需要读取用户上传过来的txt文件,但不确定txt文件的字符集
UTF-16、UTF-8(带BOM)、Unicode可以根据前三个字节区别
- public String getTxtEncode(FileInputStream in) throws IOException{
- byte[] head = new byte[3];
- in.read(head);
- String code = "GBK";
- if (head[0] == -1 && head[1] == -2 )
- code = "UTF-16";
- if (head[0] == -2 && head[1] == -1 )
- code = "Unicode";
- //带BOM
- if(head[0]==-17 && head[1]==-69 && head[2] ==-65)
- code = "UTF-8";
- if("Unicode".equals(code)){
- code = "UTF-16";
- }
- return code;
- }
但不带BOM的UTF-8和GBK前三个字节不确定,用以上方法无法区别
通过在google上搜索发现不带BOM的识别是Java遗留的一个bug,呵呵,终于找到根源了,Java提供了此bug的解决方案
- package com.justsy.sts.utf8;
- 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;
- public 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();
- }
- }
通过使用上述InputStream类的实现可以正确的读取出不带BOM和带BOM的字符集
- package com.justsy.sts.utf8;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.nio.charset.Charset;
- public class UTF8Test {
- public static void main(String[] args) throws IOException {
- File f = new File("D:"+File.separator+"Order.txt");
- FileInputStream in = new FileInputStream(f);
- String dc = Charset.defaultCharset().name();
- UnicodeInputStream uin = new UnicodeInputStream(in,dc);
- BufferedReader br = new BufferedReader(new InputStreamReader(uin));
- String line = br.readLine();
- while(line != null)
- {
- System.out.println(line);
- line = br.readLine();
- }
- }
- }
结合Java提供的方案,我们就可以比较完整的判别出各种字符集了
- public String getTxtEncode(FileInputStream in) throws IOException{
- String dc = Charset.defaultCharset().name();
- UnicodeInputStream uin = new UnicodeInputStream(in,dc);
- if("UTF-8".equals(uin.getEncoding())){
- uin.close();
- return "UTF-8";
- }
- uin.close();
- byte[] head = new byte[3];
- in.read(head);
- String code = "GBK";
- if (head[0] == -1 && head[1] == -2 )
- code = "UTF-16";
- if (head[0] == -2 && head[1] == -1 )
- code = "Unicode";
- //带BOM
- if(head[0]==-17 && head[1]==-69 && head[2] ==-65)
- code = "UTF-8";
- if("Unicode".equals(code)){
- code = "UTF-16";
- }
- return code;
- }
相关推荐
BOM是UTF-8、UTF-16和UTF-32等编码格式中的一个可选标记,用于告知解析器文件的编码类型。例如,UTF-8的BOM是三个字节(0xEF, 0xBB, 0xBF),而UTF-16LE和UTF-16BE的BOM分别是两个字节(0xFF, 0xFE)和(0xFE, 0xFF...
它是理解项目的关键,应仔细阅读以正确使用和复现实验。 综上所述,DCGAN-pytorch实现项目提供了一个完整的深度学习模型示例,涵盖了生成对抗网络的基础理论和实践应用,对于学习和研究GANs以及PyTorch编程极具价值...
在C#编程语言中,处理文本文件时,了解文件的编码格式至关重要,因为不同的编码方式会影响到字符的正确读取和解析。本篇将介绍如何使用C#编写一个类来检测文本文件的编码,特别是区分GB2312(简体中文GBK编码)和UTF...
压缩包内的"Fishers' Java Code"很可能是包含实现上述步骤的源代码文件,可能包括数据预处理类、Fisher判别分析类、训练和分类的主程序等。通过阅读和理解这些代码,开发者可以深入理解Fisher判别分析的原理,并将其...
在训练模型时,通常会将数据集划分为训练集、验证集和测试集。训练集用于训练模型,验证集用于调整模型参数,测试集用于评估最终模型的性能。对于车辆Re-ID,评价指标可能包括平均精度(mAP)、正确匹配率(Rank-1 ...
如果压缩包中的"CPN"文件是源代码,那么可能包含用Python、Java、C++等语言实现的神经网络模型。学习和理解这些源代码可以帮助开发者深入理解神经网络的工作原理,以及如何在实际项目中应用这些模型。同时,非盗版的...
### Java题库实践知识点 #### 一、构造Circle类(圆形类) 在Java语言中,构建Circle类的主要目的是为了模拟并处理与圆相关的数学运算,如计算面积和周长等。此类的设计需遵循面向对象的基本原则,即封装、继承、...
Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据着重要地位。这份"Java-review-questions.rar_40_多选题"压缩包显然为准备Java学习者或开发者提供了一份全面的复习资料,旨在帮助他们巩固和提升...
脑电信号分析和判别模型在康复工程中的应用 脑电信号分析和判别模型是康复工程中一个重要的研究领域,该领域旨在开发和应用脑电信号分析技术来帮助痉病患者恢复运动功能和语言能力。脑电信号是大脑活动的电生理指标...
根据提供的文件信息,本文将详细解释“用Java编写的LL(1)文法判别”的核心概念、原理以及实现步骤。 ### LL(1) 文法简介 LL(1)是一种自上而下的语法分析方法,其中第一个L表示从左到右扫描输入串,第二个L表示最...
### TEC-8模型机要素解析 #### 一、TEC-8模型机概述 TEC-8模型机是一款用于教学和研究目的的微型计算机模型,它通过模拟真实计算机的工作原理来帮助学习者理解计算机系统的基本组成部分及其工作方式。本章节将基于...
在Java编程语言中,求解一次、二次及三次方程是一项常见的数学运算任务。这个程序设计的目的是通过代码实现这些方程的解析,为用户提供一个便捷的计算工具。以下是关于这个主题的一些详细知识点: 1. **一次方程**...
N-MORB和E-MORB数据挖掘--玄武岩判别图及洋中脊源区地幔性质的讨论.pdf
该数据集的子集以`.zip`格式提供,内含一个名为`LFW_30x15.mat`的文件,这是对原始LFW数据集的裁剪和尺寸调整版本,主要针对人脸部分进行了处理,将每个图像缩放为30x15像素的大小,以降低计算复杂度并提高处理速度...
- **不使用 XML 文件**:可以通过编程的方式设置配置信息,这种方式更为灵活但相对繁琐。 - **获取 SqlSession**:`SqlSessionFactory` 可用于创建 `SqlSession` 对象,它是应用程序与数据库交互的主要接口。 ```...
若栈为空而还有右括号未处理,或者所有括号处理完毕后栈非空,则说明括号不匹配。 #### 实验内容与步骤 1. **定义链表节点结构体**: ```c++ typedef struct LinkNode { char data; struct LinkNode *next; }...
- 生成对抗网络(GAN):用于图像生成和风格迁移,由生成器和判别器两个网络组成,通过对抗训练达成生成目标。 3. 优化算法与损失函数: - 常见优化器:SGD、Adam、Adagrad等,它们在梯度下降的基础上进行了改进...
- 还可能包含数据集,这些数据集包含专家的行为轨迹,供IRL算法学习和训练。 5. **学习逆强化学习的意义**: - 通过IRL,我们可以让机器学习到人类的智慧,从而在没有明确的奖励信号时也能做出合理的决策。 - 它...
在SIMCA-P 11中,用户可以处理大量的多维数据,通过主成分分析(PCA)、偏最小二乘回归(PLS)和部分最小二乘判别分析(PLS-DA)等统计工具来解析数据结构。PCA用于降维和可视化,PLS则常用于建立预测模型,而PLS-DA...
这些图像被标记为10个相互排斥的类别之一:飞机、汽车(但不包括卡车或皮卡)、鸟、猫、鹿、狗、青蛙、马、船和卡车(但不包括皮卡)。每个类有6000个图像,每个类有5000个训练图像和1000个测试图像。 决定图像是否属于一...