Browsed by
Category: j2me

换种角度,豁然开朗

换种角度,豁然开朗

  之前做过一个E6的屏幕扩展插件,没有成功。先介绍下那个插件的作用吧。E6是触屏手机,所以它没有数字键,而大家都知道,几乎所有的游戏都要数字键才能正常操作,如何解决这个问题呢?当时我的想法是利用java的继承特性,用自己写的Canvas去继承别人程序里的Canvas,这样就可以在自己的Canvas中添加触屏事件的功能,并模拟出按键的效果。   结果当然是失败了,不过目前我还是不知道是为什么(哪位大虾指点下)。今天想说的是,上次我的想法是让自己去继承别人,可是当时我为什么没有想到用别人来继承自己呢?把自己写的Canvas当作一个中间的接口,也是可以实现自己预期的目标吧。   常常都在说换个角度,或许就会豁然开朗,事实上的确如此,唯一的问题是,面对问题时,能够做到这一点吗?

一个单例模式的变种形式—-可控多例模式

一个单例模式的变种形式—-可控多例模式

单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。 实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。 这里,我不想多说这个模式,而是说明另一种模式。 假设系统中出现这样的情况:系统中不仅仅只需要出现1个实例,而是最多只能出现2个或3个呢?单例模式明显就不能用了,怎么办,其实也很简单,修改单例的类,让其返回对象的函数检测系统中已存在的实例个数,如果超过了,就抛出异常,否则则返回一个实例。 另外,因为要严格控制系统中已创建实例的个数,就需要一个计数器,java和c++不同,没有析构函数,所以,就要求使用者调用一个释放的方法,来告诉系统已经消除了该实例。 既然已经想到了修改某个单例类,能不能更简单一些,创造一个框架性的东西,让想采用该模式设计的类,只要继承这套框架就可以使用了呢?也是可以的。具体是这样实现的,利用jdk1.5的模板功能,创造一个Count的模板类,该类负责统计数目和抛出异常,所有想使用这个模式的类,继承该Count类就可以了。具体请看下面的代码。 /** * 单例模式的变种,可以控制建立实例的数目 * * 计数器类 * * 如果超过建立制定数目的实例,则抛出MaxInstanceException异常 * * @author roye( royelee_007@hotmail.com ) * @version 0.1 * @see MaxInstanceException */class Count<T>{ public static int objectNum = 0;  private static int OBJECT_SUM = 1;  protected Count() throws MaxInstanceException{  //System.out.println("objectNum = " + objectNum);    ++objectNum;    if(objectNum > OBJECT_SUM){   throw new MaxInstanceException();  }    init(); }  /*  * 可以改变此函数来获得不同的初始化效果  */ protected void init(){  //…. }  /*  * 每一个实例被释放时,一定要调用这个函数,否则无法创建新的实例  */ public void release(){  –objectNum; }  /*  * 指定某个类的最大实例数目,默认为1个实例  */ protected static void setObejctSum(int s){  OBJECT_SUM  = s; }} class MaxInstanceException extends Exception{}; /* * 一个例子,请注意该类的构造函数和getInstance函数的形式。必须按照此形式,才能顺利采用Count的框架 * * @author roye( royelee_007@hotmail.com ) * @version 0.1 * @see Count<T> */class Print extends Count<Print>{ private Print() throws MaxInstanceException{ }  public static…

Read More Read More

wtk命令行打包备忘录

wtk命令行打包备忘录

今天群里有人问,不过这东西不需要记住,故整理出来备忘吧。   1 Build javac   -bootclasspath ….libcldcapi10.jar;….libmidpapi20.jar   -d tmpclasses   src*.java preverify   -classpath ….libcldcapi10.jar;….libmidpapi20.jar   -d classes   tmpclasses -d <output directory> 2 Package Create a manifest file containing the appropriate attributes as specified in the MIDP specification. You can use any text editor to create the manifest file. A manifest might have the following contents, for example: MIDlet-1: My MIDlet, MyMIDlet.png, MyMIDlet MIDlet-Name: MyMIDlet MIDlet-Vendor: My Organization MIDlet-Version: 1.0 MicroEdition-Configuration: CLDC-1.0 MicroEdition-Profile: MIDP-2.0 jar cfm <file>…

Read More Read More

脚本引擎之探索56.com

脚本引擎之探索56.com

最近一直没有做flvExport的升级,因为都在忙着弄脚本引擎。   脚本引擎的确可以加快开发的速度,今天是实验下了56.com,用了原来一半的时间,就写出了一个探索脚本,非常的方便。   这里是我今天探索出的100多个flv视频下载地址,喜欢朋友可以点击这里看看。     另外,还得说下56.com真是牛人比较多啊,破解出它的flv源地址还真比其他的网站要麻烦很多。   简单说下它是怎么做的吧。在它的每个具体视频页面中,存放着一个加密后的字符串,我们对这个串解密,可以获得一个js的对象。这个对象存放着某个flv的如"id", "URL_host", "URL_pURL","URL_sURL", "user_id", "URL_URLid"等信息。得到这些信息后,再通过它的一个固定算法,才能算出具体的flv源地址。

Be Careful With Transient Data

Be Careful With Transient Data

Be Careful With Transient Data Java’s serialization provides an elegant, and easy to use mechanism for making an object’s state persistent. While controlling object serialization, we might have a particular object data member that we do not want the serialization mechanism to save. To turn off serialization on a certain field of an object, we tag that field of the class of our object with the Java’s "transient" keyword. This, to low-level parts of the Java virtual machine, is an…

Read More Read More

脚本探索初步试验成功!

脚本探索初步试验成功!

一直以来,FlvExport的一大局限在于只能我自己添加探索站点,不利于扩展,而对于探索不同的站点来说,其实都是采用一些写好的模块化的东西,所不同的仅仅是组合的方式,正是这个原因,我最近一直在研究利用脚本探索,把写好的东西更加灵活的组合在一起。   今天,初步实验成功,可以根据我写的脚本探索出网页的具体内容了。   脚本采用xml语言,附上一个例子: <?xml version = "1.0" encoding = "UTF-8" standalone = "no"?><target name = "Sina Digest" default = "getNameAndURL"> <task name = "init">  <define name = "flvNames" type = "vector"/>  <define name = "flvURLs" type = "vector"/>  <define name = "curLine" type = "string"/>  <define name = "curURL" type = "string"/>  <define name = "curName" type = "string"/> </task> <task name = "getNameAndURL" depends = "init">  <connection type = "url" value = "http://v.blog.sina.com.cn/">   <getLine dest = "curLine"/>   <while condition = "NE" left = "curLine" right = "null">    <regex src…

Read More Read More

java的关键字volatile的用途

java的关键字volatile的用途

java的关键字volatile的用途 在实际工作中很少有用到volatile这个关键字,今天在看一段开源代码时碰到它,查了一下它的用法 : 用在多线程,同步变量 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A) What does volatile do? This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords: int i1;              int geti1() {return i1;} volatile int i2;              int geti2() {return i2;} int i3;               synchronized int geti3() {return i3;}geti1() accesses the value currently stored in i1…

Read More Read More

关于E6Plugin的总结

关于E6Plugin的总结

因为E6按键不够,所以做了以下尝试,结果还是失败了,希望以后能想到好的办法吧。 1.实验按键响应:    E6侧面除了两个音量键外,还有3个音乐播放键,想看看着几个键能不能用上,于是进行J2ME环境下的试验,没想到,keyPressed根本就不理这几个按键,郁闷~~相当于没有用。 2.写外挂插到J2ME程序中:    既然不让用按键,触屏总能用吧,先写一个程序,它实现这样的功能:        a.在屏幕上绘制出半透明的键盘。        b.用户点选键盘后,会调用Canvas的keyPressed函数,传递进相应的按键。模拟用户键盘输入。     程序很简单,放到E6上实测成功。(代码见后附录1)     下一步,就是把这个程序加到别人发的包里,看实际效果。     一般来说,用J2ME发布的程序都经过混淆,这样可以增加别人反编译后阅读源码的难度,并且可以减小程序包的大小,可正是这个混淆,非常麻烦。这里我拿GL的午夜台球做试验,解开包后,发现有5个class,其中c.class正是其Canvas的类,于是反编译之,把反编译得到的代码拷贝到Eclipse中,出现n条错误,原来,混淆器会把同种类的类型用最小的字母来顺序命名,比如有2个int变量,则它们会命名为a,b。可是如果有2个long变量,它们还是会命名为a,b。这样就麻烦了,因为在编辑环境下,这样的命名方式属于重复的,只能把它们改成不同的名称才能编译通过,因为本人比较懒,不愿意改动那10000多行的代码,所以这样直接在其Canvas中加入自己代码的方式就这么被否决了。     接着想这样:用自己写PlugCanvas继承别人的Canvas,并且在Paint中加入绘制键盘图形,在pointerPressed处理用户点击屏幕并模拟输出到别人程序的KeyPressed中。     进行试验,发现一般混淆后class都变成了final的,真郁闷,想直接继承还不行,必须修改class文件,研究发现,用UE打开class文件,查找0x31,在一些Import后的那个31就是modifier,把这个31改成21后,这个class就不是final了(附2:modifier的常量表)     事情还并没有结束,因为要在屏幕上绘制出键盘,就必须重构paint函数,可paint函数也被弄成了final的,又要改calss,这回没有上次那么简单,必须要找到对应的Method列表,找到paint函数,然后才能修改,一番研究之后发现,在class文件中查找0x11095e,把它改成0x01095e就可以把paint函数变成非final的了。(具体的方法可以参考class文件结构的文章http://java.chinaitlab.com/Jvm/24631.html)        本来,事情到这儿就应该完成了,所有文件都已经编译成功,可当我把class放到WTK下运行却无法运行,实在没辙了,等想到好的方法时再继续吧。 附1:import javax.microedition.lcdui.Canvas;import javax.microedition.lcdui.Graphics;import javax.microedition.lcdui.Image; /** * E6键盘插件 *  * @author roye * */public class PluginCanvas extends Canvas { private int keyV;  final int width = 240;  final int height = 160;  int[] colorData;  int[][] mapKeyTable = { { 31, 32, 33 }, { 34, 35, 36 }, { 37, 38, 39 },   { 40, 30, 41 } };  char[] keyStr = { ‘1’, ‘2’, ‘3’,…

Read More Read More

使java程序只有一个实例保留在内存中

使java程序只有一个实例保留在内存中

使java程序只运行一次使java程序只运行一次,既只允许一个实例保留在内存中 主要是利用fileLock类来实现对文件加锁,实现上述目的(多说无益,代码如下): package com.neonway.oneinstance; import java.io.*; import java.nio.channels.*; public class OneInstance {    /**     * @param args     */    public static void main(String[] args) {     try {             System.out.println("progran start …");             String filename = new String("test.txt");             File testFile = new File(filename);            RandomAccessFile raf;            FileChannel fc;            FileLock fl;             testFile.createNewFile();             if (testFile.canWrite()) {                raf = new RandomAccessFile(testFile, "rw");                fc = raf.getChannel();                fl = fc.tryLock();                 if ((fl == null) || (fl.isValid() == false)) {                    System.out.println("this is useing by another program!");               …

Read More Read More

一个java字符编码解码不易发现的错误

一个java字符编码解码不易发现的错误

我在使用一个流时,用的InputStreamReader来读取,因为预先知道该流是采用UTF-8编码的,所以我用了new InputStreamReader(is, "UTF-8")语句创建Reader。 后来在使用中,我又使用了如下的语句try { String tmp = new String(xr.getBytes(), "UTF-8");} catch (UnsupportedEncodingException e) {  // TODO Auto-generated catch block  e.printStackTrace();}得到的tmp输出时,如果是英文的就正确,如果是中文的就会乱码(后面查资料得知utf编码兼容iso8859-1编码,所以英文不会出错,编码基本知识见附录) 是什么原因呢?其实是在xr.getBytes()这句话,因为它会返回系统默认编码下的byte数组,如果系统默认的不是utf-8的编码,返回的byte数组自然可能不是UTF-8,再用上UTF-8编码创建字符串,就有可能出错了。 小小的问题,但是包含了java编码的一些常识,以后一定要注意了。 ps:语句直接改成:String tmp = xr;就可以了。   附录: . 编码基本知识 最早的编码是iso8859-1,和ascii编码相似。但为了方便表示各种各样的语言,逐渐出现了很多标准编码,重要的有如下几个。 2.1. iso8859-1 属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母’a’的编码为0x61=97。 很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用iso8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然"中文"两个字不存在iso8859-1编码,以gb2312编码为例,应该是"d6d0 cec4"两个字符,使用iso8859-1编码的时候则将它拆开为4个字节来表示:"d6 d0 ce c4"(事实上,在进行存储的时候,也是以字节为单位处理的)。而如果是UTF编码,则是6个字节"e4 b8 ad e6 96 87"。很明显,这种表示方法还需要以另一种编码为基础。 2.2. GB2312/GBK 这就是汉子的国标码,专门用来表示汉字,是双字节编码,而英文字母和iso8859-1一致(兼容iso8859-1编码)。其中gbk编码能够用来同时表示繁体字和简体字,而gb2312只能表示简体字,gbk是兼容gb2312编码的。 2.3. unicode 这是最统一的编码,可以用来表示所有语言的字符,而且是定长双字节(也有四字节的)编码,包括英文字母在内。所以可以说它是不兼容iso8859-1编码的,也不兼容任何编码。不过,相对于iso8859-1编码来说,uniocode编码只是在前面增加了一个0字节,比如字母’a’为"00 61"。 需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java。 2.4. UTF 考虑到unicode编码不兼容iso8859-1编码,而且容易占用更多的空间:因为对于英文字母,unicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而产生了utf编码,utf编码兼容iso8859-1编码,同时也可以用来表示所有语言的字符,不过,utf编码是不定长编码,每一个字符的长度从1-6个字节不等。另外,utf编码自带简单的校验功能。一般来讲,英文字母都是用一个字节表示,而汉字使用三个字节。 3.在j2se下用System.out.println(System.getProperty("file.encoding"));来获取系统的默认编码。