- 浏览: 308855 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
suxiaojack:
15题,就是拿杨辉三角填充空格,答案应该是C(38,19)吧? ...
Project Euler解题汇总 013 ~ 022 -
songhaikang:
这篇文章挺好的,跟着你的步骤很快就可以入门了。非常感谢。
[转贴]Derby入门 —— (1) -
Eastsun:
呵呵,我没有Android的机器,所以兴趣不大
使用Java写的GVmaker虚拟机(开源) -
crapricorn:
那个版本的用不了虚拟键盘啊 呵呵 我们的手机没有实体键盘呀 所 ...
使用Java写的GVmaker虚拟机(开源) -
Eastsun:
crapricorn 写道希望sun侠能做出个android平 ...
使用Java写的GVmaker虚拟机(开源)
最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种电子词典)上的一种类C语言开发的GVmaker程序(不知道这里有没有玩过文曲星的,关于GVmaker可以看这里).做这个东西主要是怀念一下以前玩文曲星的日子.另外刚刚买了个智能手机,尝试一下J2ME的开发,这也是我第一个J2ME程序.
这个东西并不复杂,而且因为刚学JAVA的时候写过一个桌面版的(只不过那个写的比较烂),所以构思好大体框架把各种接口定义好后就一路写过去.待到写文件系统这一块的时候才发现J2ME对文件的访问没有C语言中那么方便,也不像J2SE中有RandomAccessFile可以用.google了一下,也没有发现相关资料.于是我自己写了个在内存中模拟C语言文件操做.当然,通过内存模拟文件操作具有很大的局限性,消耗内存并且当文件过大的时候就不适用了.不过我这个就是为了模拟器中操作文件用的,而文曲星上的程序操作的文件都不会太大,所以这样用是没问题的.
下面是实现的几个主要类:
内存文件的实现
模拟C文件操作
其中用到的两个interface:
FileSys提供了与底层文件系统的交互接口
FileInf提供了文件的相关信息
这个东西并不复杂,而且因为刚学JAVA的时候写过一个桌面版的(只不过那个写的比较烂),所以构思好大体框架把各种接口定义好后就一路写过去.待到写文件系统这一块的时候才发现J2ME对文件的访问没有C语言中那么方便,也不像J2SE中有RandomAccessFile可以用.google了一下,也没有发现相关资料.于是我自己写了个在内存中模拟C语言文件操做.当然,通过内存模拟文件操作具有很大的局限性,消耗内存并且当文件过大的时候就不适用了.不过我这个就是为了模拟器中操作文件用的,而文曲星上的程序操作的文件都不会太大,所以这样用是没问题的.
下面是实现的几个主要类:
内存文件的实现
/** * 虚拟文件,使用内存模拟文件操作<p> * 每个虚拟文件除了读写数据外,还有三个属性:position,limit,capacity<p> * 其capacity描述了这个虚拟文件当前能容纳的最大数据量,这个值不能从外部修改,但在向其写入数据时根据需要内部会适当扩充其capacity<p> * limit描述的是虚拟文件当前存储的数据总量,外部可以读取或修改或增加数据到虚拟文件.这个值在调用readFromStream时自动初始化,并且内部自动维护<p> * position表示下一个读/写数据的地址,相当于普通文件操作中的文件指针.其初始值应该由调用者在调用readFromStream方法后正确设置<p> * 对于一个含有数据,并正确初始化的VirtualFile,应有以下关系成立:<p> * 0<=position<=limit<=capacity * @author Eastsun * @version 2008-2-25 */ public final class VirtualFile { //每次增量的最小值:128K private static final int MIN_ADD_CAPS = 0x20000; private static final int MAX_COUNT = 5; //内存块,最多支持5块,也就是640K,对GVmaker来说足够了 private byte[][] bufs = new byte[MAX_COUNT][]; //caps[k]表示第0,..k-1块内存的总容量 private int[] caps = new int[MAX_COUNT + 1]; //内存块数量 private int count; //当前所在内存块下标 private int index; //文件长度 private int limit; //the index of the next element to be read or written private int position; /** * 使用一个初始容量构造VirtualFile * @param size */ public VirtualFile(int size) { bufs[0] = new byte[size]; for (int n = 1; n <= MAX_COUNT; n++) { caps[n] = size; } count = 1; } /** * 得到该VirtualFile总容量 * @return capacity */ public int capacity() { return caps[count]; } /** * 得到VirtualFile中实际存储数据的长度,也就是文件的长度 * @return length of file */ public int limit() { return limit; } /** * 得到VirtualFile中的读写指针位置,也就是文件指针 * @return position */ public int position() { return position; } /** * 设置文件指针 * @param newPos 新的指针位置 * @return newPos 设置后的指针,若出错返回-1 */ public int position(int newPos) { if (newPos < 0 || newPos > limit) { return -1; } position = newPos; //修改index,使其满足caps[index]<=position<caps[index+1] while (caps[index + 1] <= position) { index++; } while (caps[index] > position) { index--; } return position; } /** * 读取文件数据,并且position加1 * @return 当前position出的文件内容;若已到文件位(>=limit()),返回-1 */ public int getc() { if (position >= limit) { return -1; } int c = bufs[index][position - caps[index]] & 0xff; position++; if (position >= caps[index + 1]) { index++; } return c; } public int putc(int ch) { if (position > limit) { return -1; } ensureCapacity(position + 1); bufs[index][position - caps[index]] = (byte) ch; position++; if (position > limit) { limit = position; } if (position >= caps[index + 1]) { index++; } return ch; } /** * 将position,limit清零 */ public void refresh() { index = position = limit = 0; } /** * 从in读取数据到VirtualFile,初始limit的值,并设置position的值为0<p> * 操作完成后关闭in * @param in 数据来源 * @throws java.io.IOException 发生IO错误 */ public void readFromStream(InputStream in) throws IOException { int size = in.available(); limit = size; ensureCapacity(size); int n = 0; while (size > 0) { size -= in.read(bufs[n++]); } in.close(); } /** * 将VirtualFile中的内容写入到out<p> * 操作完成后关闭out * @param out 写入目标 * @throws java.io.IOException 发生IO错误 */ public void writeToStream(OutputStream out) throws IOException { int n = 0; while (limit > caps[n + 1]) { out.write(bufs[n++]); } if (limit > caps[n]) { out.write(bufs[n], 0, limit - caps[n]); } out.close(); } //确保至少有minCap大小的内存可用 private void ensureCapacity(int minCap) { if (caps[count] >= minCap) { return; } //每次至少增加128K int addCap = Math.max(MIN_ADD_CAPS, minCap - caps[count]); bufs[count] = new byte[addCap]; for (int n = count + 1; n <= MAX_COUNT; n++) { caps[n] = caps[count] + addCap; } count++; } }
模拟C文件操作
/** * * @author Eastsun * @version 2008-2-22 */ public class DefaultFileModel extends FileModel { public static final String READ_MODE = "r"; public static final String READ_PLUS_MODE = "r+"; public static final String READ_B_MODE = "rb"; public static final String READ_B_PLUS_MODE = "rb+"; public static final String WRITE_MODE = "w"; public static final String WRITE_PLUS_MODE = "w+"; public static final String WRITE_B_MODE = "wb"; public static final String WRITE_B_PLUS_MODE = "wb+"; public static final String APPEND_MODE = "a"; public static final String APPEND_PLUS_MODE = "a+"; public static final String APPEND_B_MODE = "ab"; public static final String APPEND_B_PLUS_MODE = "ab+"; private static final int SEEK_SET = 0; private static final int SEEK_CUR = 1; private static final int SEEK_END = 2; //同时访问文件的最大个数 private final static int MAX_FILE_COUNT = 3; private FileSys fileSys; private String workDir; private boolean[] canRead; private boolean[] canWrite; private String[] fileNames; //是否可用,也就是是否空闲 private boolean[] usable; private VirtualFile[] files; //用于生成String的byte数组 private byte[] strBuf; //用于保存屏幕缓冲区数据 private Accessable graphBuffer; public DefaultFileModel(FileSys fileSys) { this.fileSys = fileSys; workDir = ""; canRead = new boolean[MAX_FILE_COUNT]; canWrite = new boolean[MAX_FILE_COUNT]; usable = new boolean[MAX_FILE_COUNT]; files = new VirtualFile[MAX_FILE_COUNT]; fileNames = new String[MAX_FILE_COUNT]; for (int index = 0; index < MAX_FILE_COUNT; index++) { usable[index] = true; //初始容量:64K files[index] = new VirtualFile(0x10000); } strBuf = new byte[200]; } public boolean changeDir(Getable source, int addr) { String newDir = getFileName(source, addr); FileInf inf = fileSys.getFileInf(newDir); if (inf.isDirectory()) { workDir = newDir; return true; } else { return false; } } public boolean makeDir(Getable source, int addr) { String dir = getFileName(source, addr); return fileSys.makeDir(dir); } public boolean fileList(ScreenModel screen, KeyModel key, Setable dest, int addr) { return true; } public int fopen(Getable source, int fileName, int openMode) { int num = -1; //指示文件指针位置,true开头,false为结尾 boolean pointer = true; //是否清除原有文件 boolean clear = false; for (int index = 0; index < MAX_FILE_COUNT; index++) { if (usable[index]) { num = index; break; } } if (num == -1) { return 0; } String name = getFileName(source, fileName); String mode = getString(source, openMode); FileInf inf = fileSys.getFileInf(name); if (READ_MODE.equals(mode) || READ_B_MODE.equals(mode)) { if (!(inf.isFile() && inf.canRead())) { return 0; } canRead[num] = true; canWrite[num] = false; } else if (READ_PLUS_MODE.equals(mode) || READ_B_PLUS_MODE.equals(mode)) { if (!(inf.isFile() && inf.canRead() && inf.canWrite())) { return 0; } canRead[num] = true; canWrite[num] = true; } else if (WRITE_MODE.equals(mode) || WRITE_B_MODE.equals(mode)) { if (inf.isFile() && !inf.canWrite()) { return 0; } clear = true; canRead[num] = false; canWrite[num] = true; } else if (WRITE_PLUS_MODE.equals(mode) || WRITE_B_PLUS_MODE.equals(mode)) { if (inf.isFile() && !inf.canWrite()) { return 0; } clear = true; canRead[num] = true; canWrite[num] = true; } else if (APPEND_MODE.equals(mode) || APPEND_B_MODE.equals(mode)) { if (!(inf.isFile() && inf.canWrite())) { return 0; } canRead[num] = false; canWrite[num] = true; pointer = false; } else if (APPEND_PLUS_MODE.equals(mode) || APPEND_B_PLUS_MODE.equals(mode)) { if (!(inf.isFile() && inf.canRead() && inf.canWrite())) { return 0; } canRead[num] = true; canWrite[num] = true; pointer = false; } else { return 0; } VirtualFile file = files[num]; if (clear) { file.refresh(); } else { int length = 0; try { InputStream in = fileSys.getInputStream(name); length = in.available(); file.readFromStream(in); in.close(); } catch (IOException ex) { return 0; } file.position(pointer ? 0 : length); } fileNames[num] = name; usable[num] = false; return num | 0x80; } public void fclose(int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT) { return; } if (usable[fp]) { return; } if (canWrite[fp]) { try { OutputStream out = fileSys.getOutputStream(fileNames[fp]); files[fp].writeToStream(out); } catch (IOException e) { //do nothing } } usable[fp] = true; } public int getc(int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT) { return -1; } if (usable[fp] || !canRead[fp]) { return -1; } return files[fp].getc(); } public int putc(int c, int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT) { return -1; } if (usable[fp] || !canWrite[fp]) { return -1; } return files[fp].putc(c); } public int fread(Setable dest, int addr, int size, int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT) { return -1; } if (usable[fp] || !canRead[fp]) { return -1; } VirtualFile file = files[fp]; int count = 0, b; while (count < size && (b = file.getc()) != -1) { dest.setByte(addr++, (byte) b); count++; } return count; } public int fwrite(Getable source, int addr, int size, int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT) { return -1; } if (usable[fp] || !canWrite[fp]) { return -1; } VirtualFile file = files[fp]; int count = 0, b; while (count < size) { b = source.getByte(addr++); if (file.putc(b & 0xff) == -1) { break; } count++; } return count; } public boolean deleteFile(Getable source, int addr) { return fileSys.deleteFile(getFileName(source, addr)); } public int fseek(int fp, int offset, int base) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT || usable[fp]) { return -1; } VirtualFile file = files[fp]; int pos = 0; switch (base) { case SEEK_SET: pos = offset; break; case SEEK_CUR: pos = file.position() + offset; break; case SEEK_END: pos = file.limit() + offset; break; default: return -1; } return file.position(pos); } public int ftell(int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT || usable[fp]) { return -1; } return files[fp].position(); } public boolean feof(int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT || usable[fp]) { return true; } return files[fp].position() == files[fp].limit(); } public void rewind(int fp) { fp &= 0x7f; if (fp >= MAX_FILE_COUNT || usable[fp]) { return; } files[fp].position(0); } public void dispose() { for (int index = 0; index < MAX_FILE_COUNT; index++) { fclose(index | 0x80); } } private String getFileName(Getable src, int addr) { String name = getString(src, addr); if (!name.startsWith("/")) { name = workDir + "/" + name; } return name; } private String getString(Getable src, int addr) { int length = 0; byte b; while ((b = src.getByte(addr++)) != 0) { strBuf[length++] = b; } return new String(strBuf, 0, length); } }
其中用到的两个interface:
FileSys提供了与底层文件系统的交互接口
/** * 文件系统接口<p> * 注意:方法中涉及的文件名都是GVM中用到的文件名,不一定与底层实际文件一一对应.其解释由具体实现者提供<p> * @author Eastsun * @version 1.0 */ public interface FileSys { /** * 得到该文件的InputStream,以读取其内容 * @return in 当文件存在且canRead返回true时返回指向该文件的InputStream * @throws java.io.IOException 文件不存在或不可读或发生IO错误 */ public InputStream getInputStream(String fileName) throws IOException; /** * 得到该文件的OutputStream以向其写入内容<p> * 当文件不存在时会创建一个新的文件 * @return out 返回指向该文件的OutputStream * @throws java.io.IOException 若文件不可写或发生IO错误 */ public OutputStream getOutputStream(String fileName) throws IOException; /** * 删除文件 * @param fileName 文件名 * @return true,如果删除成功 */ public boolean deleteFile(String fileName); /** * 建立文件夹 * @param dirName 文件夹名 * @return true,如果创建成功 */ public boolean makeDir(String dirName); /** * 得到指定文件/文件夹的相关信息<p> * @param fileName 文件名 * @return 其相关信息 */ public FileInf getFileInf(String fileName); }
FileInf提供了文件的相关信息
/** * 一个描述文件信息的接口 * @author Eastsun * @version 1.0 */ public interface FileInf { /** * 是否为一个文件 */ public boolean isFile(); /** * 是否为一个文件夹 * @return 当仅当存在且为文件夹时返回true */ public boolean isDirectory(); /** * 该文件夹或文件是否可读 * @return 当且仅当存在且可读时返回true */ public boolean canRead(); /** * 该文件夹或文件是否可写 * @return 当仅当存在且可写时返回true */ public boolean canWrite(); /** * 得到文件夹下文件个数 * @return 为文件夹时返回其目录下文件个数(含子目录);否则返回-1 */ public int getFileNum(); /** * 得到目录下第start个开始的num个文件名,保存到names中 * @param names 用于保存文件名的String数组 * @param start 开始文件号 * @param num 个数 * @return 实际得到的个数,如出错,返回-1 */ public int listFiles(String[] names, int start, int num); }
- src.rar (256.5 KB)
- 描述: JGVM中的大部分源代码
- 下载次数: 61
发表评论
-
JavaFX1.2的性能貌似有了很大的提升
2009-06-03 09:36 1988Osvaldo Pinali Doederlein's B ... -
Java.next:第二部分——与Java互操作
2008-09-19 23:05 1884原文地址:Java.next #2: Java Inter ... -
Java.next:第一部分——共同点
2008-09-19 13:31 1554原文地址:Java.next: Common Ground ... -
隐式转换:比动态类型更强大?
2008-09-16 18:37 1674本文内容主要来自Implicit Conversions: ... -
澄清:Java中只有按值传递,没有按引用传递!
2008-07-13 22:23 3994前言:在JAVA面试题解惑系列(五)——传了值还是传了引用 ... -
Ruby,Python不能威胁到Java的13个理由
2008-05-28 22:50 1483最近,danielstoner发表了一篇题为13 reas ... -
Java:进化的尽头
2008-05-28 17:45 1308原文地址:http://blog. ... -
《Effective Java》: Joshua Bloch访谈
2008-05-23 00:52 2620原文地址:Effective ... -
JSR 308:Java语言复杂度在恣意增长?
2008-05-20 13:54 1764原帖地址:http://www ... -
Sun能否让Java重振雄风?
2008-05-13 14:42 0原文地址:Can Sun rejuvenate Java? ... -
Groovy, JRuby, Jython, Scala:谁是胜利者?
2008-05-13 00:04 6560原文地址:Groovy, JRuby, Jython, Sca ... -
JAVA比C++更快?
2008-04-08 15:03 2053首先:我必须承认,我取JA ... -
使用StAX解析XML:使用定制事件和编写 XML
2007-10-12 23:01 2108除了提供一个低层的基 ... -
使用StAX解析XML: 拉式解析和事件
2007-10-08 20:53 33092007 年 7 月 05 日 Streaming API ... -
[转载]Streaming API for XML (StAX) 简介
2007-10-07 13:35 2310Streaming API for XML (StAX) 是用 ... -
使用CookieHandler管理Cookie数据
2007-05-31 23:22 10893前言 : 因为只学过J2SE部分,对JAVA网络编程也不甚了 ... -
浅谈HTTP的无状态性
2007-05-30 01:26 2039HTTP是Hyper Text Transf ... -
用动态代理进行修饰
2007-04-11 16:26 1860动态代理为实 ... -
一种得到代码所在行号的方法
2007-04-02 20:03 3929RT,今天在论坛上看到有人提出这个问题,马上联想 ... -
网络词汇表
2007-04-01 13:33 2000【协议 】--- protocol,指通信双方通信时遵守的一 ...
相关推荐
在J2ME中进行文件操作时,由于资源有限,需要特别关注效率和内存管理。本项目提供了一个用于删除文件的程序,适用于遵循JSR 75规范的系统。JSR 75,即“PIM API for Java Card”(个人信息管理应用程序接口),为...
在Java J2ME中进行文件操作,主要涉及到以下几个核心知识点: 1. **文件系统访问**:J2ME的`javax.microedition.io.Connector`类提供了对设备文件系统的访问接口。开发者可以通过`new FileConnection("file://path/...
模拟器会解析JAR文件中的类和资源,并在模拟的移动设备环境中执行程序。这样,你就可以在模拟的手机屏幕上看到2007版QQ的登录界面,输入账号和密码,与朋友进行聊天。 值得注意的是,由于2007年的QQ版本可能不支持...
在Java Micro Edition (J2ME) 平台上,文件操作是移动设备应用程序开发中的常见任务。J2ME 提供了基本的文件系统访问能力,但与标准 Java SE 平台相比,其功能较为有限。本篇文章将深入探讨如何在 J2ME 中进行文件的...
文件操作在J2ME中相对复杂,因为大多数移动设备的文件系统访问受到限制。javax.microedition.io.FileConnection接口提供了读写本地文件的能力。通过URI,我们可以打开、创建、删除文件或目录。在实际开发中,需要...
总的来说,J2ME的模拟浮点数类库是为了解决J2ME平台上的浮点运算需求而设计的,通过提供一系列数学函数和浮点数操作,使得开发者可以在资源受限的环境中进行复杂计算。尽管存在性能和移植性的挑战,但它极大地扩展了...
在J2ME(Java 2 Micro Edition)开发中,Pak文件是一种常见的资源打包格式,主要用于存储游戏或应用程序中的图片、音频、配置文件等非代码数据。本教程将引导你了解如何在J2ME环境中创建Pak文件,以及如何在程序中...
J2ME文件管理系统就是用于在这些设备上进行文件操作和管理的工具,它提供了对文件和目录的基本操作,如创建、读取、写入、删除以及查找等。 ### 1. J2ME文件系统模型 J2ME中的文件系统基于Java的`java.io`包,提供...
它们不支持Java SE中的File类,而是提供了`javax.microedition.io.Connector` 和 `javax.microedition.io.StreamConnection` 接口来访问和操作文件。 2. **文件访问** 在J2ME中,文件通常通过URL来表示,例如 ...
在本实验中,我们探讨了如何使用Java Micro Edition(J2ME)平台创建一个简单的小球模拟动画。J2ME是一种轻量级的Java框架,特别适合于移动设备和嵌入式系统的应用程序开发。实验的主要目标是实现一个小红球在屏幕上...
记得在操作完成后关闭流,以避免资源泄漏。 对于Image文件,处理方式类似,但需要使用特定的图像处理类,如 javax.microedition.lcdui.Image。首先,可以将Image文件加载到内存中,然后进行显示、编辑或保存。例如...
在J2ME中,开发人员需要处理资源有限的环境,因此,提供中文输入功能是一个挑战,因为这需要在小型设备上实现复杂的字符编码和输入法。 本"J2ME中文输入Demo"旨在为开发者展示如何在J2ME环境中实现基本的中文输入...
在J2ME环境中,应用程序的安装和运行受到严格的权限控制,这便是“j2me_domain_registry”文件的核心所在。这个文件实际上是一种特殊的配置文件,它包含了关于应用程序的权限信息和设备兼容性设置。 授权文件的主要...
在J2ME中,开发者可以使用MIDP自带的API进行游戏开发,但也有第三方框架,如LWUIT( Lightweight Weight User Interface Toolkit)或MIDPX,它们提供更高级的功能,如动画支持、物理引擎等,让游戏开发更加高效。...
本节将对提供的代码片段进行详细分析,以帮助理解如何在J2ME程序中读取文件。 ```java public byte[] readFile(String filepath){ byte data[] = null; try{ FileConnection fc = (FileConnection)Connector....
在J2ME应用中,图片处理是一项重要的功能,涉及到对不同格式的图片进行加载、显示和操作。下面我们将深入探讨几种常见的图片格式及其特点,以及它们在J2ME中的应用。 1. **BMP格式**: BMP是Windows操作系统中的...
本知识点将深入探讨如何将PNG图像打包为BIN文件,并在J2ME游戏中进行读取。 1. PNG打包过程: imgpacker工具就是用来完成这个任务的。PNG打包工具会将多个PNG图像合并成一个二进制(BIN)文件,以减少内存占用和...
"J2ME文件浏览器(MIDP版本)"是汪江松开发的一款针对J2ME平台的文件管理应用,它允许用户在移动设备上查看和操作本地文件系统。这一项目的核心功能包括浏览文件夹结构、查看文件信息、打开某些类型的文件(如文本...
在**J2ME_中文api.CHM**文件中,很可能是对J2ME API的中文文档,方便中国开发者查阅和理解。这类文档通常会详细介绍每个类、方法和接口的用途,提供示例代码,并解释如何在实际项目中使用这些API。 **...
在J2ME中,RecordStore是用于存储非结构化数据的主要机制。开发者可以创建、读取、更新和删除RecordStore中的记录。此外,FileConnection API允许开发者访问设备的文件系统,进行文件的读写操作。 **游戏开发** ...