網(wǎng)站:
JavaEye
作者:
iwinyeah
鏈接:
http://iwinyeah.javaeye.com/blog/170335
發(fā)表時(shí)間: 2008年03月12日
聲明:本文系JavaEye網(wǎng)站發(fā)布的原創(chuàng)博客文章,未經(jīng)作者書面許可,嚴(yán)禁任何網(wǎng)站轉(zhuǎn)載本文,否則必將追究法律責(zé)任!
在處理資源文件時(shí),我以前的做法是一次性讀入資源文件,然后再進(jìn)行處理,在處理大文件時(shí),這種方法對(duì)由于對(duì)機(jī)器內(nèi)存消耗較大而存在隱患,剛想將它改為逐字讀入的方式,在OpenBaseMovil中發(fā)現(xiàn)了這個(gè)類,很符合我的要求。關(guān)鍵代碼如下:
//... 省略
public static final String WHITESPACE = "\r\n\t ";
public String next(final String delimiters, final boolean keepWhitespace,
final boolean allowComments, final boolean reuseDelimiter,
final boolean processEscape) throws IOException {
try {
final StringBuffer token = new StringBuffer();
startLine = endLine;
startChar = endChar;
int c = in.read();
endChar++;
int status = INITIAL;
while (c != -1) { // 若還未讀到文件尾
if (c == '\n') {
endLine++;
endChar = 0;
}
switch (status) {
case INITIAL:
if (delimiters.indexOf(c) > -1) { // 如果是分隔符
lastDelimiter = (char) c;
if (isWhiteSpace(c)) {
// 如果同時(shí)也是空白符并且標(biāo)識(shí)符長(zhǎng)度大于零則返回標(biāo)識(shí)符
if (token.length() > 0) {
if (reuseDelimiter) { // 如果要重用分隔符則將它推回輸入流中
in.revert((char) c);
}
return token.toString();
}
// 如果還未有數(shù)據(jù),還要繼續(xù)往下讀
} else { // 如果不是空白符則無(wú)論標(biāo)識(shí)符長(zhǎng)度是否為零,都要返回
if (reuseDelimiter) {
in.revert((char) c);
}
return token.toString();
}
} else if (processEscape && c == '\\') {
status = ESCAPE; // 設(shè)轉(zhuǎn)義字符標(biāo)志
} else if (allowComments && c == '/') {
status = COMMENT_START; // 設(shè)注釋標(biāo)志
} else if (isWhiteSpace(c)) {
if (keepWhitespace) { // 如果空白符也要用,把它加入標(biāo)識(shí)符中
token.append((char) c);
}
} else {
token.append((char) c);
}
break;
case ESCAPE: // 處理轉(zhuǎn)義字符
switch (c) {
case 'n':
token.append('\n');
break;
case 'r':
token.append('\r');
break;
case 't':
token.append('\t');
break;
case 'b':
token.append('\b');
break;
case 'f':
token.append('\f');
break;
default:
token.append((char) c);
break;
}
status = INITIAL; // 設(shè)正常情況標(biāo)志
break;
case COMMENT_START: // 處理注釋
if (c == '/') {
status = LINE_COMMENT; // 是行式注釋
} else if (c == '*') {
status = BLOCK_COMMENT; // 是塊式注釋
} else {
status = INITIAL;
// 如果都不是則把注釋起始符和剛讀入的字符都加入到標(biāo)識(shí)符中
token.append('/').append((char) c);
}
break;
case LINE_COMMENT:
if (c == '\n') {
status = INITIAL; // 如果當(dāng)前為行注釋狀態(tài)則要一直讀到行尾才恢復(fù)正常情況標(biāo)志
}
break;
case BLOCK_COMMENT:
if (c == '*') {
status = COMMENT_END; // 如果當(dāng)前為塊注釋狀態(tài)則要一直讀到*號(hào)設(shè)為塊注釋結(jié)束狀態(tài)
}
break;
case COMMENT_END:
if (c == '/') {
status = INITIAL; // 在塊結(jié)束狀態(tài)下讀到/則為塊結(jié)束
} else {
status = BLOCK_COMMENT; // 否則塊注釋還未結(jié)束,恢復(fù)為塊注釋狀態(tài)
}
break;
}
c = in.read(); // 讀入下一字符
}
// 如果讀到文件尾時(shí),標(biāo)識(shí)符長(zhǎng)度大于零,則返回標(biāo)識(shí)符,否則返回NULL值
return token.length() > 0 ? token.toString() : null;
} catch (IOException e) {
throw new IOException("Error reading input L=" + startLine + " C="
+ startChar);
}
}
//... 省略
不過(guò)從代碼可以看出,它并不支持非Ascii編碼格式的文件,還要進(jìn)行進(jìn)一步的改造。
我的計(jì)劃是StringBuffer 用byte[]代替,增加setEncode(String encode)方法,返回字符串時(shí)使用 new String(byte[], encode)
本文的討論也很精彩,瀏覽討論>>
JavaEye推薦
文章來(lái)源:
http://iwinyeah.javaeye.com/blog/170335