在J2ME中模拟C语言中的文件操作

最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种电子词典)上的一种类C语言开发的GVmaker程序(不知道这里有没有玩过文曲星的,关于GVmaker可以看[url=http://www.ggv.com.cn/gvmaker/main.php?content=about_lava][color=red]这里[/color][/url]).做这个东西主要是怀念一下以前玩文曲星的日子.另外刚刚买了个智能手机,尝试一下J2ME的开发,这也是我第一个J2ME程序.
这个东西并不复杂,而且因为刚学JAVA的时候写过一个桌面版的(只不过那个写的比较烂),所以构思好大体框架把各种接口定义好后就一路写过去.待到写文件系统这一块的时候才发现J2ME对文件的访问没有C语言中那么方便,也不像J2SE中有RandomAccessFile可以用.google了一下,也没有发现相关资料.于是我自己写了个在内存中模拟C语言文件操做.当然,通过内存模拟文件操作具有很大的局限性,消耗内存并且当文件过大的时候就不适用了.不过我这个就是为了模拟器中操作文件用的,而文曲星上的程序操作的文件都不会太大,所以这样用是没问题的.
下面是实现的几个主要类:
[color=yellow]内存文件的实现[/color]
[code]
/**
* 虚拟文件,使用内存模拟文件操作<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++;
}
}
[/code]

[color=yellow]模拟C文件操作[/color]
[code]
/**
*
* @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);
}
}[/code]

[color=blue]其中用到的两个interface:[/color]
[color=yellow]FileSys提供了与底层文件系统的交互接口[/color]
[code]
/**
* 文件系统接口<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);
}
[/code]

[color=yellow]FileInf提供了文件的相关信息[/color]
[code]
/**
* 一个描述文件信息的接口
* @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);
}
[/code]
J2ME开发基础全接触:从入门到精通 本文还有配套的精品资源,点击获取 简介:Java 2 Micro Edition (J2ME) 是Java平台的一个子集,专为嵌入式系统和移动设备等物联网应用设计。本教程全面覆盖J2ME开发的基础知识,包括架构、开发环境、核心组件、用户界面、数据存储、网络编程、设备特性和性能优化等关键内容。开发者将学习如何利用MIDP和CLDC等技术,创建具有丰富功能的移动应用程序。本教程... 阅读详情

相关推荐

文曲星E658 预置文件 带音库 自带文件 词典 GVMAKER

文曲星E658 预置文件,可用于恢复词典音库/维修更换词典ROM后刷入。

使用Java写的GVmaker虚拟机(开源)

  这个东西我已经在文曲星论坛发过,不过估计这里玩过文曲星&Gvmaker的人不多,我先简单介绍一下这是个什么东东:[url=http://www.ggv.com.cn/newweb/default.htm]文曲星[/url]是一个电子辞典品牌,其老一些的产品多使用6502芯片,160*80的黑白LCD显示屏,并且可以通过一些方式进行编程开发。大概在5~6年前,曾经有一大群文曲星编程爱好者在这个简...

JavaSxy的专栏 2807

j2me模拟器

之前用过很多java模拟器,但是安卓版本一高就不能用了…这个是高版本安卓都能用的java模拟器

J2ME-Loader 项目推荐

J2ME-Loader 是一个专为 Android 平台设计的 J2ME 模拟器。该项目的主要编程语言是 Java,同时也使用了少量的 C 语言代码。J2ME-Loader 的目标是为 Android 用户提供一个能够运行 Java 2 Micro Edition (J2ME) 应用程序的模拟器,从而让用户能够在现代 Android 设备上体验到经典的 Java 移动游戏和应用。 ## 2. 项...

gitblog_01165的博客 515

J2ME版的GVmaker模拟器

GVmaker1.0模拟器J2ME版的Netbeans工程文件 博文链接:https://eastsun.iteye.com/blog/226840

GVmaker_app_文曲星_文曲星GVmark安卓模拟器_

文曲星电子词典GVmark游戏的安卓运行平台

FreeJ2ME终极指南:在现代设备上重温J2ME经典游戏的完整教程

你是否还记得那些在诺基亚手机上度过的美好时光?那些简单的贪吃蛇、空间大战等经典J2ME游戏,如今通过FreeJ2ME这个免费的开源模拟器,可以在你的现代电脑、树莓派甚至复古游戏机上完美重现。FreeJ2ME是一个功能强大的J2ME模拟器,支持libretro、AWT和SDL2三种前端,让你能够轻松运行那些怀旧的Java ME游戏和应用。 ## 🔍 为什么你需要FreeJ2ME? FreeJ2

gitblog_01007的博客 1062

C# NX二次开发:两种过滤器设置方案的实战解析与场景适配

本文深入解析C# NX二次开发中的两种过滤器设置方案:AddFilterHandler回调与MaskTriple属性设置。通过实战案例对比其性能差异与适用场景,帮助开发者根据需求选择最优方案,提升NX插件开发效率与交互体验。特别针对BlockStyler集成场景提供专业建议,是NX二次开发者的实用指南。

weixin_33739646的博客 845

J2ME模拟测试题及答案

这些是SUN公司的J2ME测试题,整理了一下,大家做做看能得几分(5分/题),附答案及详解 一.Programmer Quiz Find out how much you know about the J2ME Mobile Information Device Profile (MIDP) with this comprehensive quiz   1.     A midlet is a J

小毛头的BLOG 2911

谷歌浏览器崩溃排查:闪退、卡死、网页打不开的修复指南

浏览器多进程架构通过进程隔离、GPU加速和扩展沙箱提升网页渲染效率,但配置损坏、扩展冲突、显卡驱动异常或系统资源不足时,常会以闪退、卡死、白屏、内存占用飙升和能上微信却打不开网页等形式暴露。排查价值在于先分层定位系统、进程、配置扩展与网页内容,再用无痕模式、chrome://crashes、chrome://gpu和浏览器任务管理器收集证据,避免盲目重装。对办公、开发运维和日常维护场景,禁用扩展、关闭硬件加速、刷新DNS缓存、重置配置文件乃至干净重装,都是可复用的工程化处置手段。围绕谷歌浏览器崩溃的典型症状

weixin_34138056的博客 426

自绘CListCtrl时发现ON_WM_MEASUREITEM_REFLECT和DrawItem(LPDRAWITEMSTRUCT lpMeasureItemStruct) 无响应

自绘CListCtrl时发现ON_WM_MEASUREITEM_REFLECT和DrawItem(LPDRAWITEMSTRUCT lpMeasureItemStruct) 无响应 一般情况下,我们都是在 dialog 里面 放一个 list 控件,然后 用自己的类绑定自己的自绘对象,如同下面: 1.  在 dialog 里面 加一个 list 列表 2. 然后 绑定这个列表 哈哈...

mfreesky的专栏 2171

如何快速配置免费J2ME模拟器:完整实践指南

FreeJ2ME是一款功能完整的免费J2ME模拟器,支持libretro、AWT和SDL2前端,让你在现代设备上重温诺基亚、索尼爱立信等经典Java手机游戏。这个开源项目提供了完整的J2ME API实现,是重拾经典手机游戏记忆的最佳工具。 ## 🚀 FreeJ2ME模拟器核心特性 FreeJ2ME作为一款强大的J2ME模拟器,具备以下核心优势: **多平台完美兼容** 🖥️ - 支持Wi

gitblog_00449的博客 589

Scratch(四十一):升级版垃圾分类

哈喽,大家好!之前给大家展示过“Scratch(二十四):垃圾分类”。今天呢,给大家展示的Scratch是`升级版垃圾分类`。接下来,我们一起看一下效果吧。

我可以很大侠的博客 6871

免费J2ME模拟器:让诺基亚时代的经典游戏在现代设备上重生

还记得那些年,在小小的诺基亚屏幕上玩《贪吃蛇》和《空间大战》的快乐时光吗?FreeJ2ME就是这样一个神奇的项目,它让那些尘封在记忆中的J2ME经典游戏重新焕发生机。这个免费的开源模拟器支持libretro、AWT和SDL2三种前端,让你可以在现代电脑上完美运行那些曾经只能在功能手机上体验的游戏。 ## 从一次怀旧之旅开始 李华最近在整理旧物时,翻出了一部老旧的诺基亚手机。按下开机键,熟悉的开

gitblog_01147的博客 955

CT探测器普遍采用“星形拓扑+多ADC模组”架构的TDC(时间数字转换器)设计方案

本文提出一种基于TDC反馈机制的CT探测器时钟同步方法,通过延时测量、偏差计算和动态补偿三步硬件流水线,实现高精度同步。系统采用Xilinx Kintex UltraScale FPGA内置CARRY8进位链构建3.5ps分辨率的TDC,结合多级比较器和延迟单元,形成闭环反馈控制。实验表明,在512通道、1.28m传输距离下,同步精度稳定在10ps以内,较传统方案提升两个数量级,并能动态补偿干扰抖动。该方案解决了传统方法在CT旋转腔体环境下精度不足的问题,为下一代超高清CT提供了有效的时钟同步解决方案。

whm128的博客 276

Qt/C++音视频开发1-vlc解码播放

一、前言 最开始接触视频监控这块的时候,用的就是vlc作为解码的内核,主要是因为vlc使用简单方便,直接传入一个句柄即可,简单几行代码就可以实现一个视频流播放,很适合初学者使用,也推荐初学者用qt+vlc来做播放器,提供的接口还是非常友好的,而且门类特别多,想要获取媒体文件的各种信息比如宽高,设置宽高比等,直接调用接口函数传入参数就能设置。 所有用vlc做视频监控解码的人都会遇到一个问题,那就是鼠标事件被接管拦截了,不能识别鼠标事件,比如双击最大化等,这就很憋屈了,明明很好用的一个东西,怎么突然之间鼠标事件

Qt/C++视频监控/推流/物联网/大屏系统/自定义控件/UI定制/输入法 4940

免费J2ME模拟器终极指南:重拾经典手机游戏记忆 [特殊字符]

想要重温那些年玩过的诺基亚、索爱经典手机游戏吗?FreeJ2ME作为一款完全免费的J2ME模拟器,让你在现代设备上完美运行怀旧Java手机游戏!这个开源项目支持libretro、AWT和SDL2前端,是重拾经典手机游戏记忆的最佳工具。 ## 🚀 FreeJ2ME是什么? **FreeJ2ME**是一个功能完整的J2ME模拟器,能够运行各种经典的Java手机游戏和应用。它采用多前端架构设计,支

gitblog_00396的博客 905

AES-128-CMAC:背景、汽车应用、CAPL 实现与开源工具验证

本文详解车载诊断中AES-128-CMAC算法的原理与应用,涵盖其在UDS安全访问、刷写鉴权、SecOC认证及密钥派生中的核心作用。结合真实汽车电子场景,提供纯CAPL实现代码与测试脚本,并通过pycryptodome进行逐字节验证,确保算法正确性。全程基于CANoe实测数据,可直接用于HIL环境复现,助力开发者高效落地汽车网络安全方案。

蚂蚁小兵 119

终极免费J2ME模拟器:在Linux上重温诺基亚经典游戏的完整指南

还记得那些在诺基亚手机上玩《贪吃蛇》、《空间大战》的美好时光吗?**FreeJ2ME** 是一款强大的开源 **J2ME模拟器**,让你在现代Linux系统上完美运行那些经典的 **Java手机游戏**。这个免费的 **复古游戏模拟器** 支持libretro、AWT和SDL2三种前端,为怀旧玩家和技术爱好者提供了终极的 **J2ME游戏兼容性** 解决方案。 ## 为什么你需要这个J2ME模拟

gitblog_00561的博客 1001

LVGL core group焦点分组管理(lv_group.c)

lv_group_t是用于焦点管理的,将需要获取焦点的对像加入到同一个分组内,再将其通过挂到指定的事件驱动中,就可以控制焦点了。而被加入的对象又可以通过焦点状态事件和事件来控制对象的焦点逻辑了。创建好的分组通过接口挂事件驱动中,这样就可以指定一个自定义的焦点分组了。;) {if(!} }友情提示:无论是接口还是都是单例的,即被设置后前一个被设置的值就失效了;此方案可以保证焦点的唯一 性,但也一定要记住要在适合的位置设置回来,以防丢失焦点。

Bigan(安)的博客 3909

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

J2ME-Loader 项目常见问题解决方案

J2ME-Loader 是一个用于 Android 平台的 J2ME 模拟器,支持大多数 2D 和 3D 游戏(包括 Mascot Capsule 3D 游戏)。该项目的主要编程语言是 Java,同时也使用了少量的 C 语言。J2ME-Loader 允许用户在 Android 设备上运行 Java 2 Micro Edition (J2ME) 应用程序,并提供了虚拟键盘、应用程序设置、缩放支持等功...

gitblog_00904的博客 1319

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

FreeJ2ME:如何让经典J2ME游戏在你的电脑上重生

还记得那些在诺基亚手机上度过的青春时光吗?那些简单的像素游戏,虽然画面不如现在的3A大作,却承载着我们最纯粹的快乐。现在,一个名为**FreeJ2ME**的免费开源项目,正在帮助无数玩家找回那些失落的经典游戏记忆。 想象一下,你突然想起小时候玩过的《贪吃蛇》或者《空间大战》,却发现它们早已消失在应用商店中。这就是**J2ME游戏**面临的困境——随着智能手机的兴起,这些经典游戏逐渐被遗忘。但有了

gitblog_00853的博客 348

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

j2me模拟器java游戏存档修改,J2me模拟器

J2ME模拟器安卓版是一款安卓手机java模拟器,能够模拟java系统,还能运行很大一部分的java游戏和软件,J2ME模拟器安卓版让你回顾当年躲在被窝里,课桌下,玩游戏、聊天的场景,也可以让你回味一下当年那一些让我们着迷的游戏,喜欢的小伙伴,还不赶紧来牛游戏网下载!软件介绍J2ME是一款安卓端的JAVA模拟器,能够运行大部分的JAVA应用和2D、3D游戏。J2ME模拟器安卓版作为一款安卓端的JA...

weixin_42347750的博客 901

使用libGDX移植20年前的J2ME游戏《中国跳棋》

本文介绍了我使用libGDX库将20年前的游戏移植到桌面端的经验。

weixin_73899513的博客 1177

J2MEWTK提供六种模拟器

J2ME就是Java 2 Platform,micro Edition的缩写。J2ME是Java 2的一个组成部分,与J2SE、J2EE并称。根据Sun Microsystems,Inc.的定义:J2ME是一种高度优化的Java运行环境,针对市面上的大量消费类电子设备,例如Papers、cellular phones(蜂窝电话), screen-phones(可视电话?)、digital set-

u012402926的专栏 991
上一篇: 诗两首
下一篇: JAVA比C++更快?
JavaSxy
博客等级 码龄21年 1粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值