我正在尝试使用Java读取CSV文件。有些文件的开头可能有字节顺序标记,但不是全部。当存在时,字节顺序将与第一行的其余部分一起读取,从而导致字符串比较出现问题
有没有一种简单的方法可以跳过字节顺序标记
编辑:我在GitHub上发布了一个合适的版本:https://github.com/gpakosz/UnicodeBOMInputStream
这是我不久前编写的一个类,我只是在粘贴之前编辑了包名。没什么特别的,它与SUN的bug数据库中发布的解决方案非常相似。把它加入到你的代码中,你就没事了
/*____________________________________________________________________________
*
*文件:UnicodeBOMInputStream.java
*作者:Gregory Pakosz。
*日期:2005年11月2日
* ____________________________________________________________________________
*/
包com.stackoverflow.answer;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.PushbackInputStream;
/**
*这个<;代码>;Unicode数据流</代码>;类包装任何
*<;代码>;输入流</代码>;并检测是否存在任何Unicode BOM
*(字节顺序标记)在其开头,如
*<;a href=”http://www.faqs.org/rfcs/rfc3629.html“>;rfc3629-UTF-8,一种iso10646</a>;
*
*<;p>;这个
*<;a href=”http://www.unicode.org/unicode/faq/utf_bom.html“>;Unicode常见问题解答</a>;
*定义了5种BOM类型:<;ul>;
*<;李>&书信电报;预处理>;00 FE FF=UTF-32,大端头</预处理></李>;
*<;李>&书信电报;预处理>;FF FE 00 00=UTF-32,小端头</预处理></李>;
*<;李>&书信电报;预处理>;FE FF=UTF-16,大端值</预处理></李>;
*<;李>&书信电报;预处理>;FF FE=UTF-16,小端头</预处理></李>;
*<;李>&书信电报;预处理>;EF BB BF=UTF-8</预处理></李>;
*</ul></p>;
*
*<;p>;使用{@link#getBOM()}方法了解是否已检测到BOM
*或者不是。
*</p>;
*<;p>;使用{@link#skipBOM()}方法从数据库中删除检测到的BOM表
*包装<;代码>;输入流</代码>;反对。</p>;
*/
公共类UnicodeBOMInputStream扩展了InputStream
{
/**
*描述不同Unicode类型的类型安全枚举类
*博姆斯。
*/
公共静态最终类BOM
{
/**
*没有。
*/
公共静态最终BOM无=新BOM(新字节[]{},“无”);
/**
*UTF-8物料清单(EF BB BF)。
*/
公共静态最终BOM UTF_8=新BOM(新字节[]{(字节)0xEF,
(字节)0xBB,
(字节)0xBF},
“UTF-8”);
/**
*UTF-16,小端(FF FE)。
*/
公共静态最终BOM UTF_16_LE=新BOM(新字节[]{(字节)0xFF,
(字节)0xFE},
“UTF-16 little endian”);
/**
*UTF-16,大端(FE-FF)。
*/
公共静态最终BOM UTF_16_BE=新BOM(新字节[]{(字节)0xFE,
(字节)0xFF},
“UTF-16 big-endian”);
/**
*UTF-32,小端(FF FE 00)。
*/
公共静态最终BOM UTF_32_LE=新BOM(新字节[]{(字节)0xFF,
(字节)0xFE,
(字节)0x00,
(字节)0x00},
“UTF-32 little endian”);
/**
*UTF-32,大端(00 FE FF)。
*/
公共静态最终BOM UTF_32_BE=新BOM(新字节[]{(字节)0x00,
(字节)0x00,
(字节)0xFE,
(字节)0xFF},
“UTF-32大端接口”);
/**
*返回此物料清单的<;代码>;字符串<;/code>;表示形式<;代码>;<;/code>;
*价值观。
*/
公共最终字符串toString()
{
返回说明;
}
/**
*返回与此<;代码>;BOM<;/code>;值对应的字节。
*/
公共最终字节[]getBytes()
{
最终整数长度=bytes.length;
最终字节[]结果=新字节[长度];
//抄袭
数组复制(字节,0,结果,0,长度);
返回结果;
}
专用BOM表(最终字节BOM[],最终字符串描述)
{
断言(bom!=null):“无效bom:不允许为null”;
断言(description!=null):“无效描述:不允许null”;
断言(description.length()!=0):“描述无效:不允许使用空字符串”;
this.bytes=bom;
this.description=描述;
}
最终字节[];
私有最终字符串描述;
}//物料清单
/**
*构造一个新的<;code>;Unicode数据流<;/code>;来包装
*指定的<;代码>;输入流<;/code>;。
*
*@param inputStream一个<;代码>;inputStream<;/code>;。
*
*当<;code>;inputStream<;/code>;被禁用时,@引发NullPointerException
*<;代码>;空<;/code>;。
*@从指定的<;代码>;输入流<;/code>;读取时引发IOException;
*尝试检测Unicode BOM表时。
*/
公共UnicodeBOMInputStream(最终InputStream InputStream)抛出NullPointerException,
IOException
{
如果(inputStream==null)
抛出新的NullPointerException(“无效输入流:不允许null”);
in=新的PushbackInputStream(inputStream,4);
最终字节bom[]=新字节[4];
最终整型读数=整型读数(bom);
开关(读取)
{
案例4:
如果((bom[0]==(字节)0xFF)&;
(bom[1]==(字节)0xFE)和;
(物料清单[2]==(字节)0x00)&;
(bom[3]==(字节)0x00)
{
this.bom=bom.UTF_32_LE;
打破
}
其他的
如果((物料清单[0]==(字节)0x00)&;
(物料清单[1]==(字节)0x00)&;
(物料清单[2]==(字节)0xFE)&;
(bom[3]==(字节)0xFF)
{
this.bom=bom.UTF_32_BE;
打破
}
案例3:
如果((bom[0]==(字节)0xEF)&;&;
(物料清单[1]==(字节)0xBB)&;
(bom[2]==(字节)0xBF)
{
this.bom=bom.UTF_8;
打破
}
案例2:
如果((bom[0]==(字节)0xFF)&;
(bom[1]==(字节)0xFE)
{
this.bom=bom.UTF_16_LE;
打破
}
其他的
如果((bom[0]==(字节)0xFE)&;&;
(bom[1]==(字节)0xFF)
{
this.bom=bom.UTF_16_BE;
打破
}
违约:
this.bom=bom.NONE;
打破
}
如果(读取>;0)
in.未读(物料清单,0,已读);
}
/**
*返回包装中检测到的<;代码>;BOM<;/code>
*<;代码>;输入流<;/code>;对象。
*
*@返回一个<;代码>;物料清单<;/code>;值。
*/
公共最终BOM getBOM()
{
//BOM表类型是不可变的。
返回bom;
}
/**
*跳过包装中找到的<;代码>;BOM<;/code>
*<;代码>;输入流<;/code>;对象。
*
*@返回此<;代码>;数据流<;/code>;。
*
*@尝试从包装中跳过BOM表时引发IOException
*<;代码>;输入流<;/code>;对象。
*/
公共最终同步UnicodeBOMInputStream skipBOM()引发IOException
{
如果(!跳过)
{
in.skip(bom.bytes.length);
跳过=真;
}
归还这个;
}
/**
*{@inheritardoc}
*/
public int read()引发IOException
{
返回in.read();
}
/**
*{@inheritardoc}
*/
public int read(最终字节b[])引发IOException,
空指针异常
{
返回in.read(b,0,b.length);
}
/**
*{@inheritardoc}
*/
公共整数读取(最终字节b[],
最终整型关闭,
final int len)引发IOException,
空指针异常
{
返回。读取(b,关闭,len);
}
/**
*{@inheritardoc}
*/
公共长跳过(最终长n)引发IOException
{
返回。跳过(n);
}
/**
*{@inheritardoc}
*/
public int available()引发IOException
{
返回in.available();
}
/**
*{@inheritardoc}
*/
public void close()引发IOException
{
in.close();
}
/**
*{@inheritardoc}
*/
公共同步无效标记(最终整型读取限制)
{
in.标记(readlimit);
}
/**
*{@inheritardoc}
*/
public synchronized void reset()引发IOException
{
in.reset();
}
/**
*{@inheritardoc}
*/
公共布尔标记受支持()
{
在.markSupported()中返回;
}
私有最终PushbackInputStream输入;
私人最终物料清单;
私有布尔值=false;
}//Unicode数据流
你是这样使用它的:
导入java.io.BufferedReader;
导入java.io.FileInputStream;
导入java.io.InputStreamReader;
公共最终类UnicodePutStreamUsage
{
公共静态void main(最终字符串[]args)引发异常
{
FileInputStream fis=新的FileInputStream(“test/officing_bom.txt”);
UnicodeBOMInputStream ubis=新的UnicodeBOMInputStream(fis);
System.out.println(“检测到的BOM:+ubis.getBOM());
System.out.print(“在不跳过BOM的情况下读取文件内容:”;
InputStreamReader isr=新的InputStreamReader(ubis);
BufferedReader br=新