Look into it ~

present
随笔 - 32, 文章 - 0, 评论 - 3, 引用 - 0
数据加载中……

Serializing an Image

Serializing an Image

Creating an image from an array of data is an easy task, but to create a byte-array of data from an image is a little more complicated. But it's required if you want to send a modified image to a server.

To create a byte-array of data from an image, we can use the getRGB(..) method in the image class in MIDP 2.0. From the getRGB method we get an int-array of data containing all the ARGB values of each pixel in the image. Integers in java are four bytes, so we need to split each int value into four byte values.

To mask out each of the bytes in the int we can use the 'AND &' operator and the 'shift-right >>' operator. Here's an example:

int ARGB = 0xFFFFFFFF;  // AARRGGBB 
int a = (ARGB & 0xFF000000);
int r = (ARGB & 0x00FF0000);
int g = (ARGB & 0x0000FF00);
int b = (ARGB & 0x000000FF);
// Here we move each bit to the right.
a = (a >> 24); // a = 0x000000FF
r = (r >> 16); // r = 0x000000FF
g = (g >> 8); // g = 0x000000FF
b = b;        // b = 0x000000FF

When we convert the integer to a byte, there are some problems since there are only signed bytes in Java. A byte may contain values between –128 and 127 and from our integer we'll have a value between 0 and 255.

Here are some conversion examples:

Integer val 127 = byte val 127. 
Integer val 128 = byte val –128.
Integer val 255 = byte val –1.
byte ba = (byte)(a);  // if a=0x000000FF (255), then ba = -1
byte br = (byte)(r);
byte bg = (byte)(g);
byte bb = (byte)(b);

We have to loop though each pixel in the image and get each pixel value to our byte-array. When that's done, we can send the image to a server where we can convert the byte-array back to a integer-array and then show our picture.

So, when we convert the byte back to an integer we have to check if the byte value is less than zero.

Int a, r, g, b;
If(ba<0)
     a = 256 – a;

Now our new integer value will be between 0 and 255 and we just have to use the 'shift-left <<' operator and add the values together to get our new int-array.

a = (a << 24);
r = (r << 16);
g = (g << 8);
b = (b);
  0xFF000000 (a)
+ 0x00FF0000 (r)
+ 0x0000FF00 (g)
+ 0x000000FF (b)
= 0xFFFFFFFF (argb)
int ARGB = a+r+g+b;

After the integer-array is recreated we can use the createRGBImage(..) method in the Image class to create our image.

Be aware that the byte-array is quite large as it contains all of the ARGB values for each pixel. If an image is 100*60 px, where each pixel is four bytes, the byte array will be 24kb.

ImageBytearryConvert.rar

posted @ 2008-09-11 17:09 LukeW 阅读(244) | 评论 (0)编辑 收藏

HTTP头信息

HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送WWW方式的数据,关于HTTP 协议的详细内容请参 考RFC2616。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求,请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户 信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应,相应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以 及可能的实体内容。

通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行, 一个或者多个头域,一个只是头域结束的空行和可 选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域 值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。

通用头域
通用头 域包含请求和响应消息都支持的头域,通用头域包含Cache-Control、 Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via。对通用头域的扩展要求通讯双方都支持此扩 展,如果存在不支持的通用头域,一般将会作为实体头域处理。下面简单介绍几个在UPnP消息中使用的通用头域。


  Cache-Control头域
Cache -Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置 Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如 下:

Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。


  Date头域
Date头域表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。

  Pragma头域
  Pragma头域用来包含实现特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache- Control:no-cache相同。

请求消息
请求消息的第一行为下面的格式:
MethodSPRequest-URISPHTTP-VersionCRLFMethod 表示对于Request-URI完成的方法,这个字段是大小写敏感的,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、 TRACE。方法GET和HEAD应该被所有的通用WEB服务器支持,其他所有方法的实现是可选的。GET方法取回由Request-URI标识的信息。 HEAD方法也是取回由Request-URI标识的信息,只是可以在响应时,不返回消息体。POST方法可以请求服务器接收包含在请求中的实体信息,可 以用于提交表单,向新闻组、BBS、邮件群组和数据库发送消息。

SP表示空格。Request-URI遵循URI格式,在此字段 为星 号(*)时,说明请求并不用于某个特定的资源地址,而是用于服务器本身。HTTP- Version表示支持的HTTP版本,例如为HTTP/1.1。CRLF表示换行回车符。请求头域允许客户端向服务器传递关于请求或者关于客户机的附加 信息。请求头域可能包含下列字段Accept、Accept-Charset、Accept- Encoding、Accept-Language、Authorization、From、Host、If-Modified-Since、If- Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、 Proxy-Authorization、Range、Referer、User-Agent。对请求头域的扩展要求通讯双方都支持,如果存在不支持的请 求头域,一般将会作为实体头域处理。

  典型的请求消息:
GET http://download.microtool.de:80/somedata.exe
Host: download.microtool.de
Accept:*/*
Pragma: no-cache
Cache-Control: no-cache
Referer: http://download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-

上例第一行表示HTTP客户端(可能是浏览器、下载程序)通过GET方法获得指定URL下的文件。棕色的部分表示请求头域的信息,绿色的部分表示通用头部分。

  Host头域
  Host头域指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回。

  Referer头域
Referer 头域允许客户端指定请求uri的源资源地址,这可以允许服务器生成回退链表,可用来登陆、优化cache等。他也允许废除的或错误的连接由于维护的目的被 追踪。如果请求的uri没有自己的uri地址,Referer不能被发送。如果指定的是部分uri地址,则此地址应该是一个相对地址。

  Range头域
Range头域可以请求实体的一个或者多个子范围。例如,
表示头500个字节:bytes=0-499
表示第二个500字节:bytes=500-999
表示最后500个字节:bytes=-500
表示500字节以后的范围:bytes=500-
第一个和最后一个字节:bytes=0-0,-1
同时指定几个范围:bytes=500-600,601-999

但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200 (OK)。

  User-Agent头域
User-Agent头域的内容包含发出请求的用户信息。

响应消息
响应消息的第一行为下面的格式:
HTTP-VersionSPStatus-CodeSPReason-PhraseCRLF

HTTP -Version表示支持的HTTP版本,例如为HTTP/1.1。Status- Code是一个三个数字的结果代码。Reason-Phrase给Status-Code提供一个简单的文本描述。Status-Code主要用于机器自 动识别,Reason-Phrase主要用于帮助用户理解。Status-Code的第一个数字定义响应的类别,后两个数字没有分类的作用。第一个数字可 能取5个不同的值:

1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求

响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和 Request-URI进一步的信息。响应头域包含Age、Location、Proxy-Authenticate、Public、Retry- After、Server、Vary、Warning、WWW-Authenticate。对响应头域的扩展要求通讯双方都支持,如果存在不支持的响应头 域,一般将会作为实体头域处理。

典型的响应消息:

HTTP/1.0200OK
Date:Mon,31Dec200104:25:57GMT
Server:Apache/1.3.14(Unix)
Content-type:text/html
Last-modified:Tue,17Apr200106:46:28GMT
Etag:"a030f020ac7c01:1e9f"
Content-length:39725426
Content-range:bytes554554-40279979/40279980

上例第一行表示HTTP服务端响应一个GET方法。棕色的部分表示响应头域的信息,绿色的部分表示通用头部分,红色的部分表示实体头域的信息。

  Location响应头
Location响应头用于重定向接收者到一个新URI地址。

  Server响应头
Server响应头包含处理请求的原始服务器的软件信息。此域能包含多个产品标识和注释,产品标识一般按照重要性排序。

  实体
请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息,实体头包括Allow、Content- Base、Content-Encoding、Content-Language、 Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、 Etag、Expires、Last-Modified、extension-header。extension-header允许客户端定义新的实体 头,但是这些域可能无法未接受方识别。实体可以是一个经过编码的字节流,它的编码方式由Content-Encoding或Content-Type定 义,它的长度由Content-Length或Content-Range定义。

  Content-Type实体头
Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型 Content-Range实体头
Content-Range实体头用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth 


例如,传送头500个字节次字段的形式:Content-Range:bytes0- 499/1234如果一个http消息包含此节(例如,对范围请求的响应或对一系列范围的重叠请求),Content-Range表示传送的范围, Content-Length表示实际传送的字节数。

  Last-modified实体头

应答头 说明
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文 档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的 下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept- Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表 示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过 byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentTyep。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified 文 档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档 才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。
注 意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的 HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。

注意Refresh的意义是“N秒之后 刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访问指定页面”。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则 可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。

注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie 设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate 客 户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如, response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。
注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。

posted @ 2008-09-10 12:05 LukeW 阅读(233) | 评论 (0)编辑 收藏

j2me获取系统信息

在J2ME开发中,我们经常需要和手机系统进行交互,获得一些和系统相关的信息,在J2ME API设计中,提供了一系列的系统属性
表1   CLDC、MIDP和JTWI属性
属性名称
属性作用
microedition.profiles
代表手机支持的MIDP版本,返回格式值为“MIDP-1.0”或“MIDP-2.0”
microedition.configuration
代表手机支持的CLDC版本,返回格式值为“CLDC-1.0”或“CLDC-2.0”
microedition.locale
代表手机所在的国家或地区,返回值格式为“en-US”
microedition.platform
代表手机的品牌和型号,Nokia手机的返回值格式为“Nokia6310i/4.42”
microedition.encoding
代表手机默认的字符集名称,返回值格式为“ISO-8859-1”
microedition.commports
代表手机可以使用的串口列表,返回值中各个串口之间使用逗号分隔
microedition.hostname
MIDP2.0定义,代表本地主机名称,需要手机支持。
microedition.jtwi.version
代表手机支持的JTWI版本,值必须是“1.0”
 表2 可选包属性
属性名称
属性作用
microedition.media.version
代表手机支持的MMAPI版本,如果不支持则返回null
microedition.pim.version
代表手机支持的PIM API版本,如果不支持则返回null
microedition.m3g.version
代表手机支持的M3G API版本,如果不支持则返回null
microedition.location.version
代表手机支持的Location API版本,如果不支持则返回null
Bluetooth.api.version
代表手机支持的BT API版本,如果不支持则返回null
microedition.io.file.
FileConnection.version
代表手机支持的FC API版本,如果不支持则返回null
microedition.global.version
代表手机支持的Mobile Internationalization API(JSR-238)版本,如果不支持则返回null
microedition.chapi.version
代表手机支持的CH(Content Handler) API(JSR211)版本,如果不支持则返回null
microedition.sip.version
代表手机支持的SIP API版本,如果不支持则返回null
 表3 MMAPI属性
属性名称
属性作用
supports.mixing
代表手机是否支持混音(同时播放多个Player),返回值为“true”或“false”
supports.audio.capture
代表手机是否支持声音捕获(录音),返回值为“true”或“false”
supports.video.capture
代表手机是否支持视频捕获(录像),返回值为“true”或“false”
supports.recording
代表手机是否支持记录(record),返回值为“true”或“false”
audio.encodings
代表手机支持的声音格式,返回值格式为“encoding=audio/wav”,多个格式之间使用至少一个空格进行间隔
video.encodings
代表手机支持的视频格式,返回值格式为“encoding=video/3gpp”,多个格式之间使用至少一个空格进行间隔
video.snapshot.encodings
代表手机使用getSnapshot方法获得的视频快照格式,返回值格式为“encoding=png”,多个格式之间使用至少一个空格进行间隔
streamable.contents
代表手机支持的流媒体格式,返回null代表不支持
表4 Wireless Messaging API属性
属性名称
属性作用
wireless.messaging.sms.smsc
代表手机发送短信时的短信服务中心号码
表5 FileConnection API
属性名称
属性作用
fileconn.dir.photos
代表手机中存储照片和其它图片的目录,例如“file:///c:/My files/ Images /”
fileconn.dir.videos
代表手机中存储视频的目录,例如“file:///c:/My files/Video clips/”
fileconn.dir.tones
代表手机中存储声音的目录,例如“file:///c:/My files/Tones/”
fileconn.dir.memorycard
代表手机中存储卡的根目录。例如“file:///d:/”
fileconn.dir.private
(Nokia S40不支持) 
代表手机中MIDlet的私有工作目录,例如“file:///c:/System/MIDlets/[1015f294]/scratch”
fileconn.dir.photos.name
代表手机中图片目录的名称,例如“Images”
fileconn.dir.videos.name
代表手机中视频目录的名称,例如“Video clips”
fileconn.dir.tones.name
代表手机中声音目录的名称,例如“Sound clips”
file.separator
代表手机中的文件分隔符,例如“/”
fileconn.dir.memorycard.name
代表手机中存储卡的名称,例如“Memory card”
 使用这些属性,可以获得在程序运行过程中需要的很多和系统相关的信息,也可以使用表2中的属性来获得手机是否支持对应的可选包等信息。
实际使用示例:String name = System.getProperty(“microedition.platform”);

注意:如果需要获得JVM或jad文件中的信息,需要使用MIDlet类中的getAppProperty方法,其属性名则需要查阅jad文件的设定,和本文所述的属性名无关。

posted @ 2008-08-28 16:43 LukeW 阅读(282) | 评论 (0)编辑 收藏

HTTP请求头信息

HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST)。如有必要,客户程序还可以选择发送其他的请求 头。大多数请求头并不是必需的,但Content-Length除外。对于POST请求来说Content-Length必须出现。

下面是一些最常见的请求头:

Accept:浏览器可接受的MIME类型。
Accept-Charset:浏览器可接受的字符集。
Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
Connection: 表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点, Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然 后在正式写出内容之前计算它的大小。
Content-Length:表示请求消息正文的长度。
Cookie:这是最重要的请求头信息之一,参见后面《Cookie处理》一章中的讨论。
From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
Host:初始URL中的主机和端口。
If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。
Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。
JAVA手机网[www.cnjm.net]

Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。
UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型。
有关HTTP头完整、详细的说明,请参见http://www.w3.org/Protocols/ 的HTTP规范。

java 读取方法

  Enumeration headerNames = request.getHeaderNames();
         while(headerNames.hasMoreElements()) {
             String headerName = (String)headerNames.nextElement();
             out.println("<p>"+headerName+"  "+request.getHeader(headerName)+"</p>");
         }

posted @ 2008-08-20 13:58 LukeW 阅读(157) | 评论 (0)编辑 收藏

期待eclipse RCP:Design, Coding and Packaging 第二版

eclipse_rcp_book_cover

《Eclipse Rich Client Platform – Design, Coding and Packaging》是在Eclipse 3.1发布以后,针对 Eclipse RCP 平台的一本非常重要,也非常有用的书。 最近,这本书的作者们开始了第二版的编写,将以最新的 Eclipse 3.4 为基础,并且预计在08年年底正式发布。 新书的作者透露,第二版中除了以3.4为基础,还将加入很多新东西:

非常期待着这本书。

posted @ 2008-08-20 10:13 LukeW 阅读(126) | 评论 (0)编辑 收藏

eclipse真机调试J2me程序

简单记录一下遇到的几个问题:

1. 真机调试其实是厂商SDK根据JAVA的调试API层实现的.

2. 要注意JAD文件中字段的长度不要过长, 否则会报错, 无法调试.

3. 相比较, netbeans进行真机调试要方便一些. 当然eclipse应该也没问题(懒得实验了..).

posted @ 2008-08-15 15:22 LukeW 阅读(294) | 评论 (0)编辑 收藏

J2me的List总结

List控件是使用频率非常高的显示控件之一了。但是最近发现它的一点不足。
那就是getSelectedIndex()函数,一般情况下它都能正常工作。唯有在List处于复选模式(MULTIPLE)时,使用该函数无法获得当前高亮条选中索引,而总是返回-1。

参考List控件的源代码,可以发现,List类实现了Choice接口,并且包含一个ChoiceGroup成员。它才是实现List大部分功能的大功臣。
List类的getSelectedIndex()方法,实际上就是ChoiceGroup的getSelectedIndex()方法。大家可以参考Doc中关于ChoiceGroup的getSelectedIndex()方法的如下部分。
“For ChoiceGroup objects of type MULTIPLE, this always returns -1 because no single value can in general represent the state of such a ChoiceGroup.”

就是说,List在多选模式(MULTIPLE)下,我们是无法获取当前高亮条所在项的索引值的。
当然,你可以自己数数。

也许你觉得这个问题不算严重,也许吧。但我觉得对于程序员来说,最严重的问题就是理解发生偏差。
比如我,在发现这个问题之前。凭借多年的编程经验,我很确定很确定的认为,这个getSelectedIndex()永远能够获得当前光标所指项的索引值。
……当错误来临时,我百思不得其解。最后,花了好些时间去调试才发现,那个值总等于-1。操!花了太多时间去猜测原本正确的代码。
我只想告诉大家,真正耗费时间最多,让人最恶心的错误,往往就是这样的问题。再操!

那么有什么简单的解决办法么?
我可以很负责任的告诉你,自己写一个多选的List控件吧,记住不要让getSelectedIndex()总返回-1。即使是多选,有时候也是需要这个值的。

也许你想继承List,然后重载getSelectedIndex()方法。但你无法重载List的keyPressed方法(其实List等Screen控件都用Canvas写的)。
……或许还能想到别的什么好办法。不过我的选择是自己写一个List控件代替它(如果对它感兴趣,请回复,改天我在弄出来吧)。

至于List的其它功能,就没什么重复的必要的,看看文档吧。

posted @ 2008-08-15 15:20 LukeW 阅读(285) | 评论 (0)编辑 收藏

Vector 总结

Vector是在java编程中比较常用的动态数组。一直以为它是个数组的链表,当内存不够用了,就新申请一个capacityIncrement大小的数组,连到原来的链表上。
在仔细阅读源代码后发现,Vector并没有任何链表的性质。它是一个纯粹的数组。当内存不够用时,就重新初始化一个容量较大新数组,然后使用System.arraycopy()函数将原有的数组copy到新的数组当中。

System.arraycopy()是一个由系统平台来实现的函数,这样的系统调用性能是比较高的。
即使如此,我们在写程序时,注意initialCapacity(初始容量)和capacityIncrement(增量)的设置,将会有效的减少重新定义数组并且拷贝数组的次数。

例如:
Vector v = new Vector(1010);//初始容量为10,增量10
Integer[] ints = new Integer11;
for (int i = 0; i < ints.length; i++) {
ints 
= new Integer(i);
v.addElement(ints);
}

在这里,当v添加第11个Integer的时候,v就会自动创建一个长度为20的数组(当前容量+增量),以后每次装满数组,都会重新按增量追加数组长度。
所以,设置一个合适的初始容量和增量,将会提高Vector的效率。千万别像我一样,把它当做链表。因为链表在增长空间时是不会影响到以前使用的空间和数据的。

我想指出一点,因为Vector中存储的,实际上都是Object变量,大家可以把它理解为指针。重新初始化Vector内置的数组并且拷贝,相当于对一个指针数组进行操作,并不等同于对输入类型的重新分配内存。
就是说Vector的重新分配,不论进行多少次都不涉及到Integer对象的创建,拷贝等工作。它只是重新创建并拷贝“指针”数组,也就是Object数组。
此外,java中有一个容易被忽视的基本概念。当某个对象再没有指向该对象的引用时,垃圾回收器才会自动将其自动释放。不小心使用,很容易给程序造成内存问题。
例如:

Vector v = new Vector(1010);//初始容量为10,增量10
Integer[] ints = new Integer11;
for (int i = 0; i < ints.length; i++) {
ints 
= new Integer(i);
v.addElement(ints);
}
ints 
= null;//对它的释放将造成数组元素的释放。但是由于v中还保存有元素的引用,所以这些Integer对象并不会被回收。
我强调这个问题,是因为曾经写过一段代码:
Image img = Image.createImage(”/xxx.png”);
Image img2 = img;
这张图片非常大,在使用完img之后,我释放掉它,然后重新申请另一个图片。于是,内存爆了。因为img2仍然持有xxx.png的引用,所以无法释放。
Vectro中存储的也是引用,所以在使用时应该更加注意编程规范,以免发生类似的问题。其实应该尽量避免使用多个引用。

上面说了这些题外话,正是想警告各位程序员,Vector是一个可变的Object数组,一个引用数组。所以请大家使用时要小心,别想当然的以为它是一个容器,它里面存储的可不是对象,而是引用。
而且,在释放曾经加入到vector的对象时,对象本身并不会被真正释放,得到回收。只是原有的引用无法再使用罢了。

最后还有一点技巧。
应该尽量使用索引获取对象,避免使用IndexOf()方法。把它当做堆栈来使用时更应该注意,要避免使用insertElementAt()方法。
此外,j2me中的Stack类是基于Vector实现的,使用时也要留心。

posted @ 2008-08-15 15:19 LukeW 阅读(179) | 评论 (0)编辑 收藏

汉字转拼音

     摘要: 在网上参考了一些汉字转换到拼音的资料。思路应该只有以下两种。 1,查表法。这样做需要一个庞大的映射表,在j2me环境下不大合适。不过效果好,有些还支持多音字。 2,使用GB字库的映射关系。因为GB2312及其扩展GBK的汉字编码都根据区位于拼音存在映射关系。 实际上网络上的大部分文章都是根据第二种方法来实现的。 我也是采用这种方法,因为它基本上可以利用GB2312字库,直接映射成拼音。...  阅读全文

posted @ 2008-08-15 15:15 LukeW 阅读(401) | 评论 (0)编辑 收藏

GB2312转换Unicode

之前的文章介绍了在j2me环境下GB2312转换为UTF-8的方法。
后来继续对编码及char类型进行学习,发现一些有趣的问题。
首先java环境下的char类型变量,实际上就是以unicode方式存储的。
所以以下方法有效:

输入unicode编码的byte数组,即可两两拼接成一个char。
而String类型实际上就是在char数组的基础上衍生出来的。大家可以参考cldc的源代码。
public static String read_Uni(byte[] word_unicode) {
        StringBuffer stringbuffer 
= new StringBuffer("");
        
for (int j = 0; j < word_unicode.length;) {
            
int l = word_unicode[j++];
            
int h = word_unicode[j++];
            
char c = (char) ((l & 0xff| ((h << 8& 0xff00));
            stringbuffer.append(c);
        }
        
return stringbuffer.toString();
    }


j2me环境下也是如此。
所以在第一次给出的转换类中,提供的gb2312到utf-8直接转换的快速方法。现在看来是画蛇添足了。

根据以上经验,更新转换类如下:
public class HGB2312 {
 
        
private byte[] map = new byte[15228];
 
        
public HGB2312() throws Exception {
            InputStream is 
= getClass().getResourceAsStream("/gb2u.dat");
            is.read(map);
            is.close();
        }
 
        
public String gb2utf8(byte[] gb) {
            StringBuffer sb 
= new StringBuffer();
            
int c, h, l, ind;
            
for (int i = 0; i < gb.length;) {
                
if (gb[i] >= 0) {
                    sb.append((
char) gb[i++]);
                } 
else {
                    h 
= 256 + gb[i++];
                    l 
= 256 + gb[i++];
                    h 
= h - 0xA0 - 1;
                    l 
= l - 0xA0 - 1;
                    
if (h < 9) {
                        ind 
= (h * 94 + l) << 1;
                        c 
= (byte2Int(map[ind]) << 8 | byte2Int(map[ind + 1]));
                        sb.append((
char) c);
                    } 
else if (h >= 9 && h <= 14) {
                        sb.append((
char0);
                    } 
else if (h > 14) {
                        h 
-= 6;
                        ind 
= (h * 94 + l) << 1;
                        c 
= (byte2Int(map[ind]) << 8 | byte2Int(map[ind + 1]));
                        sb.append((
char) c);
 
                    } 
else {
                        sb.append((
char0);
                    }
                }
            }
            
return sb.toString();
        }
 
        
private int byte2Int(byte b) {
            
if (b < 0) {
                
return 256 + b;
            } 
else {
                
return b;
            }
        }
    }


这个方法明显要比第一次快很多了,直接查表,然后拼接成String,不需要转换成utf-8编码。

数据文件请在http://download.csdn.net/source/263609获取

总之,java中的char类型实际上是存储了unicode编码。目前在nokia 5300上测试通过。
我觉得其它机器也应该是这样。如果哪位大侠知道这方面的资料,请赐教。

posted @ 2008-08-15 14:58 LukeW 阅读(599) | 评论 (0)编辑 收藏

仅列出标题
共3页: 上一页 1 2 3 下一页