J2ME 技术的学习与实践者

2008年3月12日 #

j2me如何读取网上资源文件例如文本文件,图形文件,欢迎投稿!

j2me如何读取网上资源文件例如文本文件,图形文件。

例如,读取www.kingdart.cn/jaccount/imobile.png 转换为Image
又例如:读取www.kingdart.cn/jaccount/readme.txt 转换为String

只在模拟器上成功我也会,要求是真机上成功!

posted @ 2008-03-25 22:56 iwinyeah 阅读(613) | 评论 (1)编辑 收藏

[导入]WTK模拟器之RMS(5 还是有可能在手机上做出文件式RMS的)


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/174850  发表时间: 2008年03月22日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

我的错!在没有认真阅读FileConnection文档之后就妄下结论.最近下载了fileconnection_spec_1.00文档,发现其中有一个方法
public java.io.OutputStream openOutputStream(long byteOffset)
throws java.io.IOException
该方法在打开输出流时可指定写入的位置,写入的数据将覆盖旧数据,利用这个方法,还是有可能在手机上实现文件式RMS的.

现在我正在做手机理财JAccount的文件备份和恢复,还分不出身来尝试,有兴趣的朋友可以自已试一下如果OK了,别忘了告诉我一声哦!
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/174850

posted @ 2008-03-22 17:01 iwinyeah 阅读(590) | 评论 (3)编辑 收藏

[导入]FileConnection如何使用?


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/174754  发表时间: 2008年03月22日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

由于要为手机理财JAccount增加数据导出到文本文件功能,我为其增加了exportToFile(String fileName)方法,使用Moto模拟器(A630)时发现装入JAR阶段已出错,错误的信息是:
ALERT: Unable to load class javax/microedition/io/file/FileConnection,RAZR_V3则正常.要知道,我从未打算为不同的手机制作不同的JAR,我计划是在代码中检查该手机是否支持FileConnection,若支持的话,菜单项才增加备份和恢复命令项.
如果所有不支持FileConnection的手机都不能装入的话,那不是只能为支持的开发一个版本,不支持的又开发另一个版本?
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/174754

posted @ 2008-03-22 10:55 iwinyeah 阅读(322) | 评论 (0)编辑 收藏

[导入]字段输入流FieldInuptStream


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/174645  发表时间: 2008年03月21日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

/**
 * --------------------------------------------------
 * 字段输入流
 * --------------------------------------------------
 * 从DataInputStream继承
 * 主要增加了从文本格式输入流中读入数据字段的能力
 * --------------------------------------------------
 * 
 * @author iwinyeah 李永超
 * @version 1.0.0
 * */

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FieldInputStream extends DataInputStream {
	public final static int BIN_MODE = 0;

	public final static int TXT_MODE = 1;

	int mode;

	public FieldInputStream(InputStream in, int mode) {
		super(in);
		this.mode = mode;
	}

	public boolean getBoolean() throws IOException {
		if (mode == 0) {
			return readBoolean();
		} else {
			if ("1".equals(next())) {
				return true;
			}
			return false;
		}
	}

	public byte getByte() throws IOException {
		if (mode == 0) {
			return readByte();
		} else {
			return (byte) Integer.parseInt(next());
		}
	}

	public short getShort() throws IOException {
		if (mode == 0) {
			return readShort();
		} else {
			return (short) Integer.parseInt(next());
		}
	}

	public int getInt() throws IOException {
		if (mode == 0) {
			return readInt();
		} else {
			return Integer.parseInt(next());
		}
	}

	public long getLong() throws IOException {
		if (mode == 0) {
			return readLong();
		} else {
			return Long.parseLong(next());
		}
	}

	public String getString() throws IOException {
		if (mode == 0) {
			if (read() == 0) {
				return null;
			} else {
				return readUTF();
			}
		} else {
			return next();
		}
	}

	// 取下一标识符
	private byte[] buffer = new byte[255];

	private int length = 0;

	private boolean eos = false;

	private final static int INITIAL = 0;

	private final static int ESCAPE = 1;

	private final static int COMMENT_START = 2;

	private final static int LINE_COMMENT = 3;

	private final static String WHITESPACE = "\n\r\t";

	public String next() throws IOException {
		length = 0;
		int c = in.read();
		int status = INITIAL;
		READWHILE: while (c != -1) { // 一直读到文件尾

			switch (status) {
			case INITIAL:
				if (c == '\n' || c == '\t') { // 如果是分隔符
					break READWHILE;
				} else if (c == '\\') {
					status = ESCAPE; // 设转义字符标志
				} else if (c == '/') {
					status = COMMENT_START; // 设注释标志
				} else {
					if (WHITESPACE.indexOf(c) < 0) {
						append(c);
					}
				}
				break;

			case ESCAPE: // 处理转义字符
				switch (c) {
				case 'n':
					append('\n');
					break;

				case 'r':
					append('\r');
					break;

				case 't':
					append('\t');
					break;

				case 'b':
					append('\b');
					break;

				case 'f':
					append('\f');
					break;

				default:
					append(c);
					break;
				}
				status = INITIAL; // 设正常情况标志
				break;

			case COMMENT_START: // 处理注释
				if (c == '/') {
					status = LINE_COMMENT; // 是行式注释
				} else {
					status = INITIAL;
					// 如果都不是则把注释起始符和刚读入的字符都加入到标识符中
					append('/');
					append(c);
				}
				break;

			case LINE_COMMENT:
				if (c == '\n') {
					status = INITIAL; // 如果当前为行注释状态则要一直读到行尾才恢复正常情况标志
					break READWHILE;
				}
				break;
			}
			c = in.read(); // 读入下一字符
		}

		if (c == -1) {
			eos = true;
		}

		// 如果读到文件尾时,标识符长度大于零,则返回标识符,否则返回NULL值
		if (length <= 0) {
			return null;
		} else {
			return new String(buffer, 0, length, "UTF-8");
		}
	}

	// 将读入的字符加入缓冲区
	private void append(int c) {
		// 缓冲区不足时自动扩展
		if (length >= buffer.length) {
			byte[] xBuffer = new byte[buffer.length + 16];
			System.arraycopy(buffer, 0, xBuffer, 0, buffer.length);
			buffer = null;
			buffer = xBuffer;
		}

		buffer[length++] = (byte) c;
	}

	public boolean eos() {
		return eos;
	}
}

请参看我的另一篇文章:字段输出流FieldOutputStreamhttp://iwinyeah.javaeye.com/admin/blogs/174644
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/174645

posted @ 2008-03-21 22:19 iwinyeah 阅读(162) | 评论 (0)编辑 收藏

[导入]字段输出流FieldOutputStream


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/174644  发表时间: 2008年03月21日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

我的FieldOutputStream继承了DataOutputStream,这样就可以只更改很少量的代码就实现了既支持原生格式又支持文本方式输出了,稍候一段时间手机理财将可以实现备份和恢复(文本格式)功能了.
package util;
/**
 * --------------------------------------------------
 * 字段输出流
 * --------------------------------------------------
 * 从DataOutputStream继承
 * 主要增加了向输出流写入文本格式的数据字段的能力
 * 文本格式流将由TAB分隔字段,回车换行符分隔记录
 * --------------------------------------------------
 * 
 * @author iwinyeah 李永超
 * @version 1.0.0
 * */

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FieldOutputStream extends DataOutputStream {
	public final static int BIN_MODE = 0;

	public final static int TXT_MODE = 1;

	private final static byte[] fieldSplit = {'\t'};

	private final static byte[] recordSplit = {'\r','\n'};

	private int mode;
	
	private boolean nextEnd = false;

	public FieldOutputStream(OutputStream out, int mode) {
		super(out);
		this.mode = mode;
	}

	// 接着写入的是否最后一个字段
	// 写第一个字段前以参数false调用它
	// 写最后一个字段前以参数false调用它
	public void setNextEnd(boolean end){
		nextEnd = end;
	}
	
	public void putBoolean(boolean value) throws IOException {
		if (mode == 0) {
			writeBoolean(value);
		} else {
			out.write(value ? '1' : '0');
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

	public void putByte(byte value) throws IOException {
		if (mode == 0) {
			writeByte(value);
		} else {
			out.write(String.valueOf(value).getBytes("UTF-8"));
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

	public void putShort(short value) throws IOException {
		if (mode == 0) {
			writeShort(value);
		} else {
			out.write(String.valueOf(value).getBytes("UTF-8"));
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

	public void putInt(int value) throws IOException {
		if (mode == 0) {
			writeInt(value);
		} else {
			out.write(String.valueOf(value).getBytes("UTF-8"));
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

	public void putLong(long value) throws IOException {
		if (mode == 0) {
			writeLong(value);
		} else {
			out.write(String.valueOf(value).getBytes("UTF-8"));
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

	public void putString(String value) throws IOException {
		if (mode == 0) {
			if (value == null) {
				writeByte(0);
			} else {
				writeByte(1);
				writeUTF(value);
			}
		} else {
			if(value != null){
				byte[] b = value.getBytes("UTF-8");
				for(int i = 0; i < b.length; i++){
					if(b[i] == '\n'){
						out.write('\\');
						out.write('n');
					}
					else if(b[i] == '\r'){
						out.write('\\');
						out.write('r');
					}
					else if(b[i] == '\t'){
						out.write('\\');
						out.write('t');}
					else if(b[i] == '\b'){
						out.write('\\');
						out.write('b');}
					else if(b[i] == '\f'){
						out.write('\\');
						out.write('f');
					}else{
						out.write(b[i]);
					}
				}				
			}
			out.write(nextEnd ? recordSplit : fieldSplit);
		}
	}

}


读回请参看另一篇:字段输入流FieldInputStream.http://iwinyeah.javaeye.com/admin/blogs/174645
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/174644

posted @ 2008-03-21 22:16 iwinyeah 阅读(200) | 评论 (0)编辑 收藏

[导入]日期处理类(忽略时间)


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/173704  发表时间: 2008年03月19日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

我的一个日期处理类,解决了时区问题,给有需要的人。
package util;

/**
 * --------------------------------------------------
 * 日期转换对象
 * --------------------------------------------------
 * 主要提供日期与1970-01-01后的天数的转换和到字符串的转换
 * --------------------------------------------------
 * 
 * @author iwinyeah 李永超
 * @version 1.0.0
 * */

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DateUtil {
	private static Calendar _calendar = Calendar.getInstance(); // 用于日期计算

	private static long MSEC_EVERYDAY = 86400000L; // 一天的微秒数

	private static int rawOffset = TimeZone.getDefault().getRawOffset();

	/**
	 * 将日期转换为1970-01-01后的天数
	 * 
	 * @param Date
	 *            theDate 要计算天数的日期
	 * @return int 所传入日期与1970-01-01相差的天数
	 */
	public static int dateToDay(Date theDate) {
		return (int) ((theDate.getTime() + rawOffset) / MSEC_EVERYDAY);
	}

	/**
	 * 将1970-01-01后的天数转换为日期
	 * 
	 * @param int
	 *            要取的日期与1970-01-01相差的天数
	 * @return Date theDate 与1970-01-01相差相应天数的日期
	 */
	public static Date dayToDate(int day) {
		return new Date(day * MSEC_EVERYDAY);
	}

	/**
	 * 取今天与1970-01-01相差的天数
	 * 
	 * @return int 取今天与1970-01-01相差的天数
	 */
	public static int toDay() {
		return (int) ((System.currentTimeMillis() + rawOffset) / MSEC_EVERYDAY);
	}

	/**
	 * 将日期转换为年月日字符串
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return String 对应日期年月日形式的字符串
	 */
	public static String getYMD(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		return _calendar.get(Calendar.YEAR) % 100 + "/"
				+ (_calendar.get(Calendar.MONTH) + 1 > 9 ? "" : "0")
				+ (_calendar.get(Calendar.MONTH) + 1) + "/"
				+ (_calendar.get(Calendar.DATE) > 9 ? "" : "0")
				+ _calendar.get(Calendar.DATE);
	}

	/**
	 * 将日期转换为年月字符串
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return String 对应日期年月形式的字符串
	 */
	public static String getYM(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		return _calendar.get(Calendar.YEAR) + "/"
				+ (_calendar.get(Calendar.MONTH) + 1 > 9 ? "" : "0")
				+ (_calendar.get(Calendar.MONTH) + 1);
	}

	/**
	 * 将日期转换为月日字符串
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return String 对应日期月日形式的字符串
	 */
	public static String getMD(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		return (_calendar.get(Calendar.MONTH) + 1 > 9 ? "" : "0")
				+ (_calendar.get(Calendar.MONTH) + 1) + "/"
				+ (_calendar.get(Calendar.DATE) > 9 ? "" : "0")
				+ _calendar.get(Calendar.DATE);
	}

	/**
	 * 将日期转换为当月一号
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return int 对应日期所在月份第一天与1970-01-01相差的天数
	 */
	public static int getMonthFirstDay(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		_calendar.set(Calendar.DAY_OF_MONTH, 1);
		return (int) (dateToDay(_calendar.getTime()));
	}

	/**
	 * 取日期所在年份
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return int 对应日期所在年份
	 */
	public static int getYear(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		return _calendar.get(Calendar.YEAR);
	}

	/**
	 * 取日期所在月份
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return int 对应日期所在月份
	 */
	public static int getMonth(int theDay) {
		_calendar.setTime(dayToDate(theDay));
		return _calendar.get(Calendar.MONTH);
	}

	/**
	 * 取日期所在周次
	 * 
	 * @param int
	 *            theDay 与1970-01-01相差的天数
	 * @return int 对应日期所在周次
	 */
	public static int getWeek(int theDay) {
		// 1971-01-03是星期日,从该日开始计算周次
		_calendar.setTime(dayToDate(theDay));
		return (int) ((_calendar.getTime().getTime() - 172800000L) / 604800000L);
	}

}

本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/173704

posted @ 2008-03-19 12:32 iwinyeah 阅读(212) | 评论 (0)编辑 收藏

[导入]OpenBaseMovil Action <--> View <--> Controller


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/172974  发表时间: 2008年03月17日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

Action: 规定了与用户交互的View可以触发的动作,在某个View新建之后显示之前,应先为其指定具体的Action,当用户按下了相应的Command按钮之后,View将该Command对应的Action发送到该View的Controller进行处理。
//
public class Action{
    String name; // 名称 
    Command command; // 命令 
    int code; // 代码 (将由该View的传递到其Controller使用)
    Item item; // 数据项 
    boolean defaultAction; // 是否是默认的Action 
    //...省略
}


请看View的基类的代码节选
public abstract class AbstractView{

    //...省略

    // 为该View增加Action
    public void addAction( final Action action, final boolean active )
    {
        if( !actions.containsKey( action.getName() ) )
        {
            // 将Action存入Actions表中
            actions.put( action.getName(), action );
            if( active )
            {
                activateAction( action );
            }
        }
    }

    // 使Action生效可用
    private void activateAction( final Action action )
    {
        final Command command = action.getCommand();
        activeActions.put( command, action );
        final Item item = action.getItem();
        if( item == null )
        {
            addCommand( command ); // 该Action是屏幕相关的命令
        }
        else
        {
            item.addCommand( command ); // 该Action是数据项相关的命令
            if( action.isDefaultAction() )
            {
                item.setDefaultCommand( command );
            }
        }
    }

    //...省略

    // 用户按下相应的命令键后,触发执行与其关联的Action
    public void commandAction(
            final Command       command,
            final Displayable   displayable
    )
    {
        if( !handleAction( command ) )
        {
            if( displayable instanceof Choice )
            {
                AbstractController.commandAction(
                        this,
                        command,
                        (Choice) displayable
                );
            }
            else
            {
                AbstractController.commandAction( this, command );
            }
        }
    }

    // 用户在某个指定了命令的Item按下了命令按钮时触发执行与其关联的Action
    public void commandAction( final Command command, final Item item )
    {
        if( !handleAction( command ) )
        {
            AbstractController.commandAction( this, command );
        }
    }

    // 根据所触发的命令查找关联的Action,并新它发送到Controller进行处理
    public boolean handleAction( final Command command )
    {
        if( activeActions.containsKey( command ) )
        {
            final Action action = (Action) activeActions.get( command );
            // 以Action代码为参数生成ControllerEvent并传递到controller处理
            final ControllerEvent event = new ControllerEvent(
                    action.getCode(),
                    this
            );
            controller.handle( event );
            return true;
        }
        else
        {
            return false;
        }
    }

    //...省略

}

本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/172974

posted @ 2008-03-17 14:06 iwinyeah 阅读(342) | 评论 (0)编辑 收藏

[导入]Nokia 6070 报表问题解决


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/172237  发表时间: 2008年03月15日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

经过多次的尝试,终于解决了手机理财JAccount在Nokia 6070反复统计收支表和余额表时出错的问题.
原来我有两个报表上分别使用了incomeVector 和balanceVector来保存所生成的统计资料,每次统计前检查Vector是否为null,否则先置空,再重新new一个.
我尝试过new之后加了runtime.gc(),未能解决问题;
我又尝试过不置空Vector,而使用vector.removeallelements(),也不行;
我又尝试过两个报表共用一个Vector也不行;

最后,我使用两个报表共用数组来保存结果,才解决了问题,有点开心.
类似Nokia6070这种机器的JVM的内存管理的确存在很大的问题,明明有内存也用不得,真郁闷!
不过还是有点开心,毕竟解决了一个问题!
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/172237

posted @ 2008-03-15 21:43 iwinyeah 阅读(142) | 评论 (0)编辑 收藏

[导入]我在J2ME中用过的几种后台线程方法(如何选择?)


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/172200  发表时间: 2008年03月15日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

我以前在其他地方发过的贴子,这几种方式都没问题,哪种较好或者说在什么情况下用哪种方法较好呢?
// 方法一
public class firstManager implements Runnable {
  public void runTask() {
   (new Thread(this)).start();
  }
  public void run() {
   System.out.println("\nfirst thread method!");
   // Do some thing ...
  }
}
// 方法二
public class secondManager {
  private BackTask backTask;
  private Timer timer;
  public secondManager() {
   backTask = new BackTask();
   timer = new Timer();
  }
  public void runTask() {
   timer.schedule(backTask, 0);
  }
  private class BackTask extends TimerTask {
   public void run() {
    System.out.println("\nsecond thread method!");
    // Do some thing ...
   }
  }
}
// 方法三
public class thirdManager {
  private BackTask backTask;
  private int cmd = 0;
  public thirdManager() {
   backTask = new BackTask();
   backTask.start();
  }
  public void runTask() {
   synchronized (backTask) {
    cmd = 1;
    backTask.notify();
   }
  }
  private class BackTask extends Thread {
   public void run() {
    while (true) {
     try {
      if (cmd == 0) {
       synchronized (this) {
        wait();
       }
       continue;
      }
      System.out.println("\nthird thread method!");
      // Do some thing ...
     } catch (Exception e) {
     }
     cmd = 0;
    }
   }
  }
}

// 用例
public void main(){
  firstManager man1 = new firstManager();
  secondManager man2 = new secondManager();
  thirdManager man3 = new thirdManager();
  man1.runTask();
  man2.runTask();
  man3.runTask();
}

本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/172200

posted @ 2008-03-15 17:47 iwinyeah 阅读(191) | 评论 (0)编辑 收藏

[导入]OpenBaseMovil StreamParser 流标识符分段器


网站: JavaEye  作者: iwinyeah  链接:http://iwinyeah.javaeye.com/blog/170335  发表时间: 2008年03月12日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!

在处理资源文件时,我以前的做法是一次性读入资源文件,然后再进行处理,在处理大文件时,这种方法对由于对机器内存消耗较大而存在隐患,刚想将它改为逐字读入的方式,在OpenBaseMovil中发现了这个类,很符合我的要求。关键代码如下:
//... 省略
	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)) {
							// 如果同时也是空白符并且标识符长度大于零则返回标识符
							if (token.length() > 0) {
								if (reuseDelimiter) { // 如果要重用分隔符则将它推回输入流中
									in.revert((char) c);
								}
								return token.toString();
							}
							// 如果还未有数据,还要继续往下读
						} else { // 如果不是空白符则无论标识符长度是否为零,都要返回
							if (reuseDelimiter) {
								in.revert((char) c);
							}
							return token.toString();
						}
					} else if (processEscape && c == '\\') {
						status = ESCAPE; // 设转义字符标志
					} else if (allowComments && c == '/') {
						status = COMMENT_START; // 设注释标志
					} else if (isWhiteSpace(c)) {
						if (keepWhitespace) { // 如果空白符也要用,把它加入标识符中
							token.append((char) c);
						}
					} else {
						token.append((char) c);
					}
					break;

				case ESCAPE: // 处理转义字符
					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; // 设正常情况标志
					break;

				case COMMENT_START: // 处理注释
					if (c == '/') {
						status = LINE_COMMENT; // 是行式注释
					} else if (c == '*') {
						status = BLOCK_COMMENT; // 是块式注释
					} else {
						status = INITIAL;
						// 如果都不是则把注释起始符和刚读入的字符都加入到标识符中
						token.append('/').append((char) c);
					}
					break;

				case LINE_COMMENT:
					if (c == '\n') {
						status = INITIAL; // 如果当前为行注释状态则要一直读到行尾才恢复正常情况标志
					}
					break;

				case BLOCK_COMMENT:
					if (c == '*') {
						status = COMMENT_END; // 如果当前为块注释状态则要一直读到*号设为块注释结束状态
					}
					break;

				case COMMENT_END:
					if (c == '/') {
						status = INITIAL; // 在块结束状态下读到/则为块结束
					} else {
						status = BLOCK_COMMENT; // 否则块注释还未结束,恢复为块注释状态
					}
					break;

				}
				c = in.read(); // 读入下一字符
			}
			// 如果读到文件尾时,标识符长度大于零,则返回标识符,否则返回NULL值
			return token.length() > 0 ? token.toString() : null;
		} catch (IOException e) {
			throw new IOException("Error reading input L=" + startLine + " C="
					+ startChar);
		}
	}
//... 省略


不过从代码可以看出,它并不支持非Ascii编码格式的文件,还要进行进一步的改造。
我的计划是StringBuffer 用byte[]代替,增加setEncode(String encode)方法,返回字符串时使用 new String(byte[], encode)
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐




文章来源:http://iwinyeah.javaeye.com/blog/170335

posted @ 2008-03-12 07:03 iwinyeah 阅读(212) | 评论 (0)编辑 收藏