参考工具 http://akini.mbnet.fi/java/unicodereader/
Utf8BomRemover 清除bom的方法
package cn.com.do1.component.common.util;
import java.io.*;
import java.nio.charset.Charset;
public class Utf8BomRemover {
/**
* 读取流中前面的字符,看是否有bom,如果有bom,将bom头先读掉丢弃
*
* @param in
* @return
* @throws java.io.IOException
*/
public static InputStream getInputStream(InputStream in) throws IOException {
PushbackInputStream testin = new PushbackInputStream(in);
int ch = testin.read();
if (ch != 0xEF) {
testin.unread(ch);
} else if ((ch = testin.read()) != 0xBB) {
testin.unread(ch);
testin.unread(0xef);
} else if ((ch = testin.read()) != 0xBF) {
throw new IOException("错误的UTF-8格式文件");
} else {
// 不需要做,这里是bom头被读完了
// // System.out.println("still exist bom");
}
return testin;
}
/**
* 根据一个文件名,读取完文件,干掉bom头。
*
* @param fileName
* @throws java.io.IOException
*/
public static void trimBom(String fileName) throws IOException {
FileInputStream fin = new FileInputStream(fileName);
// 开始写临时文件
InputStream in = getInputStream(fin);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte b[] = new byte[4096];
int len = 0;
while (in.available() > 0) {
len = in.read(b, 0, 4096);
// out.write(b, 0, len);
bos.write(b, 0, len);
}
in.close();
fin.close();
bos.close();
// 临时文件写完,开始将临时文件写回本文件。
System.out.println("[" + fileName + "]");
FileOutputStream out = new FileOutputStream(fileName);
out.write(bos.toByteArray());
out.close();
System.out.println("处理文件" + fileName);
}
public static void main(String[] args) throws IOException {
//刪除指定文件夾下(含子文件夾)所有java文件的BOM,若構造器中參數為null則刪除所有文件頭部BOM
new Utf8BomRemover( "java" ).start( ""F:\\flwork\\gmmsDGYH\\src\\com");
}
/**
* 根据一个文件名,读取完文件,干掉bom头2 这里使用了第三方类UnicodeReader
*
* @throws java.io.IOException
*/
public void saveFile(String file) throws IOException {
InputStream in= new FileInputStream( file);
BufferedReader bre = null;
OutputStreamWriter pw = null;//定义一个流
CharArrayWriter writer = new CharArrayWriter();
//这一句会读取BOM头
//bre = new BufferedReader(new InputStreamReader(in, "UTF-8"));
//这一句会干掉BOM头
bre = new BufferedReader(new UnicodeReader(in, Charset.defaultCharset().name()));//
String line = bre.readLine();
while(line != null)
{
writer.write(line);
/*
加上这段代码可以查看更详细的16进制
byte[] allbytes = line.getBytes("UTF-8");
for (int i=0; i < allbytes.length; i++)
{
int tmp = allbytes[i];
String hexString = Integer.toHexString(tmp);
// 1个byte变成16进制的,只需要2位就可以表示了,取后面两位,去掉前面的符号填充
hexString = hexString.substring(hexString.length() -2);
System.out.print(hexString.toUpperCase());
System.out.print(" ");
}*/
line = bre.readLine();
}
writer.flush();
bre.close();
FileWriter f2 = new FileWriter(file);
writer.writeTo(f2);
f2.close();
writer.close();
}
private String extension = null ;
public Utf8BomRemover(String extension) {
super ();
this .extension = extension;
}
/** 啟動對某個文件夾的篩選 */
@SuppressWarnings ( "unchecked" )
public void start(String rootDir) throws IOException {
traverseFolder2(rootDir);
}
public void traverseFolder2(String path) throws IOException {
File file = new File(path);
if (file.exists()) {
File[] files = file.listFiles();
if (files.length == 0) {
System.out.println("文件夹是空的!");
return;
} else {
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夹:" + file2.getAbsolutePath());
traverseFolder2(file2.getAbsolutePath());
} else {
remove(file2.getAbsolutePath());
}
}
}
} else {
System.out.println("文件不存在!");
}
}
/** 移除UTF-8的BOM */
private void remove(String path) throws IOException {
saveFile(path);
trimBom(path);
}
}
第二种方法的UnicodeReader 类
package cn.com.do1.component.common.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
/**
version: 1.1 / 2007-01-25
- changed BOM recognition ordering (longer boms first)
网络地址:http://koti.mbnet.fi/akini/java/unicodereader/UnicodeReader.java.txt
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
***/
/**
* 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);
}
}