??xml version="1.0" encoding="utf-8" standalone="yes"?>在线a亚洲v天堂网2019无码,国产天堂亚洲精品,亚洲无码黄色网址http://www.tkk7.com/zjw-albert/zh-cnSat, 10 May 2025 19:14:06 GMTSat, 10 May 2025 19:14:06 GMT60oracle blob数据cd存储d的小例子(转蝲)http://www.tkk7.com/zjw-albert/archive/2007/10/27/156391.htmlzjw_albertzjw_albertSat, 27 Oct 2007 12:33:00 GMThttp://www.tkk7.com/zjw-albert/archive/2007/10/27/156391.htmlhttp://www.tkk7.com/zjw-albert/comments/156391.htmlhttp://www.tkk7.com/zjw-albert/archive/2007/10/27/156391.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/156391.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/156391.html阅读全文

zjw_albert 2007-10-27 20:33 发表评论
]]>
oracle 日期处理http://www.tkk7.com/zjw-albert/archive/2007/07/24/132084.htmlzjw_albertzjw_albertTue, 24 Jul 2007 08:43:00 GMThttp://www.tkk7.com/zjw-albert/archive/2007/07/24/132084.htmlhttp://www.tkk7.com/zjw-albert/comments/132084.htmlhttp://www.tkk7.com/zjw-albert/archive/2007/07/24/132084.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/132084.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/132084.htmlis
  V_RETURN DATE;
  V_ISSUE VARCHAR2(20) :=ISSUE;
  V_DATE_TYPE VARCHAR2(20) := DATE_TYPE;
  V_ISSUE_TYPE VARCHAR2(20) :=SUBSTR(ISSUE,1,1);
begin
  IF V_DATE_TYPE = '0' THEN
    CASE
    WHEN V_ISSUE_TYPE = '1'  Q-q?br>    THEN V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD');
         
    WHEN V_ISSUE_TYPE = '2'  Q-?br>    THEN SELECT DECODE( SUBSTR(V_ISSUE,6,2),
                        '01',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'),
                        '02',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0401','YYYY-MM-DD'),
                        '03',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0701','YYYY-MM-DD'),
                        '04',TO_DATE(SUBSTR(V_ISSUE,2,4)||'1001','YYYY-MM-DD'),TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'))
                INTO V_RETURN
          FROM DUAL;
         
    WHEN V_ISSUE_TYPE = '3' Q-?br>    THEN V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,6)||'01','YYYY-MM-DD');
         
    WHEN V_ISSUE_TYPE = '4' Q-?br>    THEN SELECT AA INTO V_RETURN FROM (
            SELECT aa ,ROWNUM BB
            FROM (
                 SELECT (TO_DATE (SUBSTR(V_ISSUE,2,6)||'01', 'yyyy-mm-dd') + ROWNUM - 1) aa  ,rownum cc
                 FROM all_objects
                 WHERE ROWNUM < TO_DATE(TO_CHAR(last_day(TO_DATE (SUBSTR(V_ISSUE,2,6)||'01', 'yyyy-mm-dd')),'YYYYMMDD'),'YYYY-MM-DD') - TO_DATE (SUBSTR(V_ISSUE,2,6)||'01', 'yyyy-mm-dd') + 1) bb 
            WHERE MOD (TO_CHAR (aa, 'dd'), 10) = 1 and to_char(aa,'dd') <> 31 )
          WHERE BB = TO_NUMBER(SUBSTR(V_ISSUE,8,2));
         
    WHEN V_ISSUE_TYPE = '5' Q-?br>    THEN SELECT MONDAY INTO V_RETURN FROM (
            select
            MONDAY.the_week,decode(sign(MONDAY.the_day-SUNDAY.the_day),-1,MONDAY.the_day,MONDAY.the_day-7) MONDAY,SUNDAY.the_day SUNDAY
            from
                 (select to_char(wwm,'WW') the_week,to_char(wwm,'D') the_daynum,wwm the_day
                  from (
                       select trunc(TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'), 'MM')+rownum-1 as wwm
                       from user_objects
                       where rownum < 366
                       )
                  where to_char(wwm,'D')=2 ) MONDAY,
                 (select to_char(wwm,'WW') the_week,to_char(wwm,'D') the_daynum,wwm the_day 
                  from (
                        select trunc(TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'), 'MM')+rownum-1 as wwm
                        from user_objects
                        where rownum < 366
                       )
                  where to_char(wwm,'D')=1 ) SUNDAY
            where MONDAY.the_week=SUNDAY.the_week)
         WHERE THE_WEEK = SUBSTR(V_ISSUE,6,2);
         
    WHEN V_ISSUE_TYPE = '6' Q-?br>    THEN V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,8),'YYYY-MM-DD');
         
    ELSE
        V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD');
    END CASE;
  ELSE
    CASE
    WHEN V_ISSUE_TYPE = '1'
    THEN V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,4)||'1231','YYYY-MM-DD');
         
    WHEN V_ISSUE_TYPE = '2'
    THEN SELECT DECODE( SUBSTR(V_ISSUE,6,2),
                        '01',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0331','YYYY-MM-DD'),
                        '02',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0630','YYYY-MM-DD'),
                        '03',TO_DATE(SUBSTR(V_ISSUE,2,4)||'0930','YYYY-MM-DD'),
                        '04',TO_DATE(SUBSTR(V_ISSUE,2,4)||'1231','YYYY-MM-DD'),
                        TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'))
                INTO V_RETURN
          FROM DUAL;
         
    WHEN V_ISSUE_TYPE = '3'
    THEN V_RETURN := TO_DATE(TO_CHAR(last_day(TO_DATE(SUBSTR(V_ISSUE,2,6)||'01','YYYY-MM-DD')),'YYYYMMDD'),'YYYY-MM-DD');
         
    WHEN V_ISSUE_TYPE = '4'
    THEN SELECT DECODE( SUBSTR(V_ISSUE,8,2),
                        '01',TO_DATE(SUBSTR(V_ISSUE,2,6)||'10','YYYY-MM-DD'),
                        '02',TO_DATE(SUBSTR(V_ISSUE,2,6)||'20','YYYY-MM-DD'),
                        '03',TO_DATE(TO_CHAR(last_day(TO_DATE(SUBSTR(V_ISSUE,2,6)||'01','YYYY-MM-DD')),'YYYYMMDD'),'YYYY-MM-DD'),
                        TO_DATE(TO_CHAR(last_day(TO_DATE(SUBSTR(V_ISSUE,2,6)||'01','YYYY-MM-DD')),'YYYYMMDD'),'YYYY-MM-DD'))
                INTO V_RETURN
          FROM DUAL;
         
    WHEN V_ISSUE_TYPE = '5'
    THEN SELECT SUNDAY INTO V_RETURN FROM (
            select
            MONDAY.the_week,decode(sign(MONDAY.the_day-SUNDAY.the_day),-1,MONDAY.the_day,MONDAY.the_day-7) MONDAY,SUNDAY.the_day SUNDAY
            from
                 (select to_char(wwm,'WW') the_week,to_char(wwm,'D') the_daynum,wwm the_day
                  from (
                       select trunc(TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'), 'MM')+rownum-1 as wwm
                       from user_objects
                       where rownum < 366
                       )
                  where to_char(wwm,'D')=2 ) MONDAY,
                 (select to_char(wwm,'WW') the_week,to_char(wwm,'D') the_daynum,wwm the_day 
                  from (
                        select trunc(TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD'), 'MM')+rownum-1 as wwm
                        from user_objects
                        where rownum < 366
                       )
                  where to_char(wwm,'D')=1 ) SUNDAY
            where MONDAY.the_week=SUNDAY.the_week)
         WHERE THE_WEEK = SUBSTR(V_ISSUE,6,2);
         
    WHEN V_ISSUE_TYPE = '6'
    THEN V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,8),'YYYY-MM-DD');
         
    ELSE
        V_RETURN := TO_DATE(SUBSTR(V_ISSUE,2,4)||'0101','YYYY-MM-DD');
    END CASE;
  END IF;
  return(V_RETURN);
end TF_ISSUE_DATE;


zjw_albert 2007-07-24 16:43 发表评论
]]>
转:(x)Oracle日期函数http://www.tkk7.com/zjw-albert/archive/2007/04/04/108427.htmlzjw_albertzjw_albertWed, 04 Apr 2007 06:39:00 GMThttp://www.tkk7.com/zjw-albert/archive/2007/04/04/108427.htmlhttp://www.tkk7.com/zjw-albert/comments/108427.htmlhttp://www.tkk7.com/zjw-albert/archive/2007/04/04/108427.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/108427.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/108427.html  Day:
  dd number 12
  dy abbreviated fri
  day spelled out friday
  ddspth spelled out, ordinal twelfth
  Month:
  mm number 03
  mon abbreviated mar
  month spelled out march
  Year:
  yy two digits 98
  yyyy four digits 1998
  
  24时格式下时间范围ؓ(f)Q?0:00:00 - 23:59:59....
  12时格式下时间范围ؓ(f)Q?1:00:00 - 12:59:59 ....
  1.
  日期和字W{换函数用法(to_date,to_charQ?
  
  2.
  select to_char( to_date(222,'J'),'Jsp') from dual
  
  昄Two Hundred Twenty-Two
  
  3.
  求某天是星期?
  select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
  星期一
  select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
  monday
  讄日期语言
  ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
  也可以这?
  TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
  
  4.
  两个日期间的天数
  select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;
  
  5. 旉为null的用?
  select id, active_date from table1
  UNION
  select 1, TO_DATE(null) from dual;
  
  注意要用TO_DATE(null)
  
  6.
  a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
  那么12?1号中?2点之后和12?L(fng)12点之前是不包含在q个范围之内的?
  所以,当时间需要精的时候,觉得to_charq是必要?
  7. 日期格式冲突问题
  输入的格式要看你安装的ORACLE字符集的cd, 比如: US7ASCII, date格式的类型就? '01-Jan-01'
  alter system set NLS_DATE_LANGUAGE = American
  alter session set NLS_DATE_LANGUAGE = American
  或者在to_date中写
  select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
  注意我这只是举了(jin)NLS_DATE_LANGUAGEQ当然还有很多,
  可查?
  select * from nls_session_parameters
  select * from V$NLS_PARAMETERS
  
  8.
  select count(*)
  from ( select rownum-1 rnum
  from all_objects
  where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
  02-01','yyyy-mm-dd')+1
  )
  where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
  not
  in ( '1', '7' )
  
  查找2002-02-28?002-02-01间除星期一和七的天?
  在前后分别调用DBMS_UTILITY.GET_TIME, 让后结果相?得到的是1/100U? 而不是毫U?.
  
  9.
  select months_between(to_date('01-31-1999','MM-DD-YYYY'),
  to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
  1
  
  select months_between(to_date('02-01-1999','MM-DD-YYYY'),
  to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
  
  1.03225806451613
  10. Next_day的用?
  Next_day(date, day)
  
  Monday-Sunday, for format code DAY
  Mon-Sun, for format code DY
  1-7, for format code D
  
  11
  select to_char(sysdate,'hh:mi:ss') TIME from all_objects
  注意Q第一条记录的TIME 与最后一行是一L(fng)
  可以建立一个函数来处理q个问题
  create or replace function sys_date return date is
  begin
  return sysdate;
  end;
  
  select to_char(sys_date,'hh:mi:ss') from all_objects;
  12.
  获得时?
  
  SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
  SQL> select sysdate ,to_char(sysdate,'hh') from dual;
  
  SYSDATE TO_CHAR(SYSDATE,'HH')
  -------------------- ---------------------
  2003-10-13 19:35:21 07
  
  SQL> select sysdate ,to_char(sysdate,'hh24') from dual;
  
  SYSDATE TO_CHAR(SYSDATE,'HH24')
  -------------------- -----------------------
  2003-10-13 19:35:21 19
  
  获取q月日与此类?
  13.
  q月日的处理
  select older_date,
  newer_date,
  years,
  months,
  abs(
  trunc(
  newer_date-
  add_months( older_date,years*12+months )
  )
  ) days
  from ( select
  trunc(months_between( newer_date, older_date )/12) YEARS,
  mod(trunc(months_between( newer_date, older_date )),
  12 ) MONTHS,
  newer_date,
  older_date
  from ( select hiredate older_date,
  add_months(hiredate,rownum)+rownum newer_date
  from emp )
  )
  
  14.
  处理月䆾天数不定的办?
  select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
  
  16.
  扑և今年的天?
  select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
  
  闰年的处理方?
  to_char( last_day( to_date('02' || :year,'mmyyyy') ), 'dd' )
  如果?8׃是闰q?
  
  17.
  yyyy与rrrr的区?
  'YYYY99 TO_C
  ------- ----
  yyyy 99 0099
  rrrr 99 1999
  yyyy 01 0001
  rrrr 01 2001
  
  18.不同时区的处?
  select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
  from dual;
  
  19.
  5U钟一个间?
  Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
  from dual
  
  2002-11-1 9:55:00 35786
  SSSSS表示5位秒?
  
  20.
  一q的W几?
  select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
  310 2002-11-6 10:03:51
  
  21.计算时,?U?毫秒
  select
  Days,
  A,
  TRUNC(A*24) Hours,
  TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
  TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
  TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
  from
  (
  select
  trunc(sysdate) Days,
  sysdate - trunc(sysdate) A
  from dual
  )
  
  
  
  select * from tabname
  order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');
  
  //
  floor((date2-date1) /365) 作ؓ(f)q?
  floor((date2-date1, 365) /30) 作ؓ(f)?
  mod(mod(date2-date1, 365), 30)作ؓ(f)?
  23.next_day函数
  next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算赗?
  1 2 3 4 5 6 7
  ?一 ?????br>

add_months(d,n)  日期d加n个月
last_day(d)  包含d的月份的最后一天的日期
month_between(d,e) 日期d与e之间的月份数Qe先于d
new_time(d,a,b)  a时区的日期和旉d在b时区的日期和旉
next_day(d,day)  比日期d晚,由day指定的周几的日期
sysdate  当前的系l日期和旉
greatest(d1,d2,...dn) l出的日期列表中最后的日期
least(d1,k2,...dn) l出的日期列表中最早的日期
to_char(d [,fmt]) 日期d按fmt指定的格式{变成字符?br>to_date(st [,fmt]) 字符串st按fmt指定的格式{成日期|若fmt忽略Qst要用~省格式
round(d [,fmt])  日期d按fmt指定格式舍入到最q的日期
trunc(d [,fmt])  日期d按fmt指定格式截断到最q的日期

Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
格式代码     说明   举例或可取值的范围
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
DD            该月某一?nbsp; 1Q?
DY    三个大写字母表示的周?nbsp;SUNQ?..SAT
DAY    完整的周几,大写英文 SUNDAYQ?..SATURDAY
MM       月䆾   1Q?2
MON      三个大写字母表示的月?nbsp;JANQ?..DEC
MONTH         完整   JANUARY,...DECEMBER
RM       月䆾的罗马数?nbsp; I,...XII
YY或YYYY      两位Q四位数字年
HH:MI:SS   Ӟ(x)分:(x)U?br>HH12或HH24  ?2时?4时昄
MI      ?br>SS      U?br>AM或PM    上下午指C符
SP      后缀SP要求拼写ZQ何数值字D?br>TH      后缀TH表示d的数字是序数 4th,1st
FM            前缀Ҏ(gu)或日或年|止填充 

Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?br>SQL> select to_char(sysdate,'yyyy-mm-dd hh:mi:ss am') from dual;

 

在oracle中有很多关于日期的函敎ͼ?

  1、add_months()用于从一个日期值增加或减少一些月?/p>

  date_value:=add_months(date_value,number_of_months)

  ?

  SQL> select add_months(sysdate,12) "Next Year" from dual;

  Next Year

  ----------

  13-11?04

  SQL> select add_months(sysdate,112) "Last Year" from dual;

  Last Year

  ----------

  13-3?-13

  SQL>

  2、current_date()q回当前?x)放时区中的当前日?/p>

  date_value:=current_date

  SQL> column sessiontimezone for a15

  SQL> select sessiontimezone,current_date from dual;

  SESSIONTIMEZONE CURRENT_DA

  --------------- ----------

  +08:00 13-11?03

  SQL> alter session set time_zone='-11:00'

  2 /

  ?x)话已更攏V?/p>

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  -11:00 12-11?03 04.59.13.668000 下午 -11:

  00

  SQL>

  3、current_timestamp()以timestamp with time zone数据cdq回当前?x)放时区中的当前日?/p>

  timestamp_with_time_zone_value:=current_timestamp([timestamp_precision])

  SQL> column sessiontimezone for a15

  SQL> column current_timestamp format a36

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  +08:00 13-11?03 11.56.28.160000 上午 +08:

  00

  SQL> alter session set time_zone='-11:00'

  2 /

  ?x)话已更攏V?/p>

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  -11:00 12-11?03 04.58.00.243000 下午 -11:

  00

  SQL>

  4、dbtimezone()q回时区

  varchar_value:=dbtimezone

  SQL> select dbtimezone from dual;

  DBTIME

  ------

  -07:00

  SQL>

  5、extract()扑և日期或间隔值的字段?/p>

  date_value:=extract(date_field from [datetime_value|interval_value])

  SQL> select extract(month from sysdate) "This Month" from dual;

  This Month

  ----------

  11

  SQL> select extract(year from add_months(sysdate,36)) "3 Years Out" from dual;

  3 Years Out

  -----------

  2006

  SQL>

  6、last_day()q回包含?jin)日期参数的月䆾的最后一天的日期

  date_value:=last_day(date_value)

  SQL> select last_day(date'2000-02-01') "Leap Yr?" from dual;

  Leap Yr?

  ----------

  29-2?-00

  SQL> select last_day(sysdate) "Last day of this month" from dual;

  Last day o

  ----------

  30-11?03

  SQL>

  7、localtimestamp()q回?x)话中的日期和时?/p>

  timestamp_value:=localtimestamp

  SQL> column localtimestamp format a28

  SQL> select localtimestamp from dual;

  LOCALTIMESTAMP

  ----------------------------

  13-11?03 12.09.15.433000

  下午

  SQL> select localtimestamp,current_timestamp from dual;

  LOCALTIMESTAMP CURRENT_TIMESTAMP

  ---------------------------- ------------------------------------

  13-11?03 12.09.31.006000 13-11?03 12.09.31.006000 下午 +08:

  下午 00

  SQL> alter session set time_zone='-11:00';

  ?x)话已更攏V?/p>

  SQL> select localtimestamp,to_char(sysdate,'DD-MM-YYYY HH:MI:SS AM') "SYSDATE" from dual;

  LOCALTIMESTAMP SYSDATE

  ---------------------------- ------------------------

  12-11?03 05.11.31.259000 13-11-2003 12:11:31 下午

  下午

  SQL>

  8、months_between()判断两个日期之间的月份数?/p>

  number_value:=months_between(date_value,date_value)

  SQL> select months_between(sysdate,date'1971-05-18') from dual;

  MONTHS_BETWEEN(SYSDATE,DATE'1971-05-18')

  ----------------------------------------

  389.855143

  SQL> select months_between(sysdate,date'2001-01-01') from dual;

  MONTHS_BETWEEN(SYSDATE,DATE'2001-01-01')

  ----------------------------------------

  34.4035409

  SQL>

  9、next_day()l定一个日期|q回q二个参数指出的日子第一ơ出现在的日期?应返回相应日子的名称字符?

  说明:

  单行日期函数

  单行日期函数操作data数据cdQ绝大多数都有data数据cd的参敎ͼl大多数q回的也是data数据cd的倹{?/p>

  add_months(,)

  q回日期d加上i个月后的l果。i可以使Q意整数。如果i是一个小敎ͼ那么数据库将隐式的他转换成整敎ͼ会(x)截去数点后面的部分?/p>

  last_day()

  函数q回包含日期d的月份的最后一?/p>

  months_between(,)

  q回d1和d2之间月的数目,如果d1和d2的日的日期都相同Q或者都使该月的最后一天,那么返回一个整敎ͼ否则?x)返回的l果包含一个分数?/p>

  new_time(,,)

  d1是一个日期数据类型,当时区tz1中的日期和时间是dӞq回时区tz2中的日期和时间。tz1和tz2时字W串?/p>

  next_day(,)

  q回日期d后由dowl出的条件的W一天,dow使用当前?x)话中给出的语言指定?jin)一周中的某一天,q回的时间分量与d的时间分量相同?/p>

  select next_day(''01-jan-2000'',''monday'') "1st monday",next_day(''01-nov-2004'',''tuesday'')+7 "2nd tuesday") from dual;1st monday 2nd tuesday03-jan-2000 09-nov-2004

  round([,])

  日期d按照fmt指定的格式舍入,fmt为字W串?/p>

  syadate

  函数没有参数Q返回当前日期和旉?/p>

  trunc([,])

  q回由fmt指定的单位的日期d.

  单行转换函数

  单行转换函数用于操作多数据类型,在数据类型之间进行{换?/p>

  chartorwid()

  c 使一个字W串Q函数将c转换为rwid数据cd?/p>

  select test_id from test_case where rowid=chartorwid(''aaaa0saacaaaaliaaa'')

  convert(,[,])

  c֭W串Qdset、sset是两?a class=bluekey target=_blank>字符?/font>Q函数将字符串c由sset字符集{换ؓ(f)dset字符集,sset的缺省设|ؓ(f)数据库的字符集?/p>

  hextoraw()

  x?6q制的字W串Q函数将16q制的x转换为raw数据cd?/p>

  rawtohex()

  x是raw数据cd字符Ԍ函数raw数据c{换ؓ(f)16q制的数据类型?/p>

  rowidtochar()

  函数rowid数据cd转换为char数据cd?/p>

  to_char([[,)

  x是一个data或number数据cdQ函数将x转换成fmt指定格式的char数据cdQ如果x为日期nlsparm=nls_date_language 控制q回的月份和日䆾所使用的语a。如果x为数字nlsparm=nls_numeric_characters 用来指定数位和千分位的分隔W,以及(qing)货币W号?/p>

  nls_numeric_characters ="dg", nls_currency="string"

  to_date([,[,)

  c表示字符Ԍfmt表示一U特D格式的字符丌Ӏ返回按照fmt格式昄的c,nlsparm表示使用的语a。函数将字符串c转换成date数据cd?/p>

  to_multi_byte()

  c表示一个字W串Q函数将c的担子截字符转换成多字节字符?/p>

  to_number([,[,)

  c表示字符Ԍfmt表示一个特D格式的字符Ԍ函数q回值按照fmt指定的格式显C。nlsparm表示语言Q函数将q回c代表的数字?/p>

  to_single_byte()

  字W串c中得多字节字W{化成{h(hun)的单字节字符。该函数仅当数据库字W集同时包含单字节和多字节字W时才用。Oracle关于旉/日期的操?/p>

  1.日期旉间隔操作

  当前旉减去7分钟的时?/p>

  select sysdate,sysdate - interval '7' MINUTE from dual

  当前旉减去7时的时?/p>

  select sysdate - interval '7' hour from dual

  当前旉减去7天的旉

  select sysdate - interval '7' day from dual

  当前旉减去7月的旉

  select sysdate,sysdate - interval '7' month from dual

  当前旉减去7q的旉

  select sysdate,sysdate - interval '7' year from dual

  旉间隔乘(sh)一个数?/p>

  select sysdate,sysdate - 8 *interval '2' hour from dual

  2.日期到字W操?/p>

  select sysdate,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-ddd hh:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-mm iw-d hh:mi:ss') from dual

  参考oracle的相兛_文档(ORACLE901DOC/SERVER.901/A90125/SQL_ELEMENTS4.HTM#48515)

  3. 字符到日期操?/p>

  select to_date('2003-10-17 21:15:37','yyyy-mm-dd hh24:mi:ss') from dual

  具体用法和上面的to_char差不多?/p>

  4. trunk/ ROUND函数的?/p>

  select trunc(sysdate ,'YEAR') from dual

  select trunc(sysdate ) from dual

  select to_char(trunc(sysdate ,'YYYY'),'YYYY') from dual

  5.oracle有毫U的数据类?/p>

  --q回当前旉 q月日小时分U毫U?/p>

  select to_char(current_timestamp(5),'DD-MON-YYYY HH24:MI:SSxFF') from dual;

  --q回当前 旉的秒毫秒Q可以指定秒后面的精?最?9)

  select to_char(current_timestamp(9),'MI:SSxFF') from dual;

  6.计算E序q行的时?ms)

  declare

  type rc is ref cursor;

  l_rc rc;

  l_dummy all_objects.object_name%type;

  l_start number default dbms_utility.get_time;

  begin

  for I in 1 .. 1000

  loop

  open l_rc for

  'select object_name from all_objects '||

  'where object_id = ' || i;

  fetch l_rc into l_dummy;

  close l_rc;

  end loop;

  dbms_output.put_line

  ( round( (dbms_utility.get_time-l_start)/100, 2 ) ||

  ' seconds...' );

  end;

 



zjw_albert 2007-04-04 14:39 发表评论
]]>
J2ME 游戏E序开发实例精讲详解(转蝲Q?/title><link>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57152.html</link><dc:creator>zjw_albert</dc:creator><author>zjw_albert</author><pubDate>Fri, 07 Jul 2006 08:15:00 GMT</pubDate><guid>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57152.html</guid><wfw:comment>http://www.tkk7.com/zjw-albert/comments/57152.html</wfw:comment><comments>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjw-albert/comments/commentRss/57152.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjw-albert/services/trackbacks/57152.html</trackback:ping><description><![CDATA[ <p>一、序a</p> <p>昨天在网上闲逛,发现一讲解用delphi实现华容道游戏的文章Q颇受启发.于是Q生了(jin)华定w游戏UL到手Zȝ冲动Q现在手机游戏琳琅满目,不一而Q华定w的实现版本也很多Q正巧不久前W者对J2ME下了(jin)一番功夫,正想借这个机?x)小试牛刀。选用J2ME的原因还有一个就是目前Java开发大行其刎ͼ无线增殖业务q猛发展QJ2ME的应用日渐活跃v来,也希望我的这文章能够ؓ(f)J2ME知识的普?qing)和开发团队的壮大推L助澜。由于长期受ISO规范的媄(jing)响,q次试牛刀我也打算늅软g工程的要求,q取瀑布式的开发模式来规划目Q也希望借此Z(x)向各位没有机?x)参与正式项目开发的读者介l一下Y件开发的程?/p> <p>q里我们先定义项目组的h员(sh)?其实只有我一个h)Q技术调研、需求分析、概要设计、详l设计、编码、测试均有笔者一人担任;工q里我找?jin)个捷径Q盗用网上现成的囄Q然后用ACDSee把它由BMP转换成PNG格式(我出于讲座的目的Q未做商业应用,应该不算侉|?Q至于发布工作,׃~少OTA服务器,此项工作不做(但是我会(x)介绍q步如何??/p> <p>接下来,我们规划一下项目实现的旉表,以我个hl验Q设惛_下:(x)技术调研用2?q部分解决项目的可行性和重大技术问题,旉?x)长一?Q需求分析用半天(毕竟有现成的东东可以参照Q只要理清思\p?jin),况且q有很多以前用过的设计模式和写好的代?Q概要设计再用半?有了(jin)需求,概要只不够是照方抓药)Q详l设计要??q一步要把所有的问题x(chng)楚,q要可能的准确描述出来)Q编码用2?其实1天就够了(jin)Q技术已l不是问题,多计划出一天来应付H发事g)Q测试用2?试应该臛_占全部项目的四分之一Q不q这个项目只是一个DemoQ也太简单了(jin))Q发布也要用上半?管我们不去实际发布它,但是q要q旉搞清楚应该如何做)Q最后就是项目ȝ和开?jin)功?旉待定)?/p> <p>二、利其器</p> <p>“公Ʋ善其事Q必先利其器”,做项目之前第一步是前期调研Q我们要做的华容道这个东东随处可见,我们要调研的是两个方面:(x)</p> <p>1. 游戏的内容:(x)游戏本n很简单,是有几个格子,Ҏ(gu)占据其中一个较大的格子Q然后被几个格子包围Q这些格子Ş状不一定相同,但是挡住?jin)曹操移动的方向Q游戏者需要挪动这些格子最l把Ҏ(gu)UdC个指定的位置才算是过养I更具体的分析我们攑֜后面需求分析和概要设计中讨论?/p> <p>2. 技术储备:(x)谈到技术,q里单介l一下J2ME.Java有三个版本,分别是J2MEQ微型版Q?J2SEQ标准版Q?J2EEQ企业版Q.J2ME是一个标准,采用Q层l构设计Q最低层是配|层QConfigurationQ也是讑֤层,其上是简表层QProfileQ?再上是应用层QApplicationQ?MIDP是Ud信息讑֤表,目前L手机支持MIDP1.0Q最新的是MIDP2.0,它比前一个版本增加了(jin)Ҏ(gu)戏的支持Q在javax.microedition.lcdui.game包中提供?jin)一些类来处理游戏中的技术,比如我们后面?x)用到的Spritec,它是用来{囄?权衡再三Q笔者决定用MIDP2.0来做开发.首先需要安装一个J2ME的模拟器Q我们就用Sun公司的WTK2.0Q我觉得Sun的东西最权威Q当然你也可以用Nokia.Siemens或是Motolora{其他模拟器Q但是他们的JDK不尽相同Q写出来的程序移植是比较ȝ(ch)的.</p> <p>Sun公司的WTK2.0可以到搜索引擎寻找下载,当然要想成功下蝲的前提是你要先注册成为Sun的会(x)员(其实q样对你是有好处的)(j)Q当下来之后是按照提示一步一步的安装Q安装好?jin)之后,我们用一?Hello World"E序开始你的J2ME之旅Q我们启动WTK2.0工具集中的KToolBarQ然后点击New Project按钮Q在弹出的输入框中输入Project Name为HelloWorld,MIDlet Class Name为Hello,然后点击Create ProjectQ开始生成项目,工具?x)弹出MIDP配置表,q里接受生成的默认|以后q可以修改)(j)点击OKQ工hC我们把写好的Java源程序放到[WTK_HOME]\apps\HelloWorld\src目录之下Q我们编辑如下代码,q保存在上述目录之下Q文件名为Hello.java?/p> <p> <br />import javax.microedition.midlet.*; <br />import javax.microedition.lcdui.*; <br />public class Hello extends MIDlet <br />{ <br />private Display display; <br />public Hello(){ <br />display =Display.getDisplay(this); <br />} <br />public void startApp(){ <br />TextBox t = new TextBox("Hello","Hello",256,0); <br />display.setCurrent(t); <br />} <br />public void pauseApp(){ <br />} <br />public void destroyApp(boolean unconditional){ <br />} <br />}<br /> (tng)</p> <p> (tng)</p> <p>保存好了(jin)之后Q点击Build按钮Q工具会(x)Z~译E序Q如无意外再点击Run按钮Q会(x)弹出一个手机界面,剩下的就不用我教?jin)吧Q用鼠标Ҏ(gu)机按键一狂点)(j)。呵呵,你的W一个J2MEE序已经OK?什么?你还?sh)炚w没懂呢(真是厉害Q不懂都能写出J2MEE序来,果然是高手)(j)Q我q里主要是介lWTK2.0工具的用,E序q不是目的,不懂的话后面q(sh)(x)有详l的解说Q这里只是带你上路.什么?你不懂JavaQ那也没有关p,后面我再讲得l一炏V?</p> <p>跌J2MEQ我们先来讲Ҏ(gu)戏的理论Q具体到华容道这个游戏,主要有三个方面,贴图Q游戏操作.逻辑判断Q这里讲讲脓(chung)图,其他两方面放在概要设计和详细设计里讲Q所谓的贴图Q其实就是画图,是在要昄囑Ş的位|上输出一副图片,Q要是牵扯到动画pȝ(ch)一些,可以使用TimerTask.Thread或Rannable之类的技?Q这副图片可以是事先准备好的也可以是临时处理的.在J2ME中有一个Imagec?专门用于理囄Q它有createImage()Ҏ(gu)Q可以直接读取图片文ӞJ2ME只支持PNG格式的图片)(j)Q也可以截取已有的图片的一部分Q这h们可以把很多囄攑֜一P然后一张一张的截下来,好处是节省存储空间和文gd旉Q对于手两者都是性能的瓶颈)(j)Q?</p> <p>J2MEq有一个Graphicsc,专门用于l图Q它有drawImage()Ҏ(gu)Q可以把一副图片在指定的位|上昄出来Q它q有drawRect()Ҏ(gu)和setColor()Ҏ(gu)Q这两个Ҏ(gu)在后面我们进行游戏操作时׃(x)用到Q这里先交代一下.有了(jin)囄和绘囄Ҏ(gu)Q还需要知道把囄到谁?li)w上QJ2ME提供?jin)一个Canvasc,字面意思就是画布,它有一个paint()Ҏ(gu)用于h面Q还有一个repaint()Ҏ(gu)用于调用paint()Ҏ(gu)Q听着有些p涂是吧Q不要紧Q我来结合具体程序讲解一下.Z(jin)今后~程的方便,我们创徏两个cImages和Draw,Images用于保存?sh)些常量值和囄QDraw主要是用于画图,q两个类的源代码如下?</p> <p>Imagescȝ源代码如下:(x) </p> <p> <br />package huarongroad; <br />import javax.microedition.lcdui.*; <br />import javax.microedition.lcdui.game.*; <br />public class Images {//保存帔R <br />//l图位置帔R <br />public static final int UNIT = 32;//方块的单位长?<br />public static final int LEFT = 10;//d的左边界点 <br />public static final int TOP = 9;//d的上边界点 <br />//地图位置帔R <br />public static final int WIDTH = 4;//地图的宽?<br />public static final int HEIGHT = 5;//地图的高?<br />//地图标记帔R <br />public static final byte CAOCAO = (byte) ′a? QA href="file://?Qfile://曹</AQ操的地图标?<br />public static final byte MACHAO = (byte) ′b?//马超的地图标?<br />public static final byte HUANGZHONG = (byte) ′c?//黄忠的地图标?<br />public static final byte GUANYU = (byte) ′d?//关羽的地图标?<br />public static final byte ZHANGFEI = (byte) ′e?//张飞的地图标?<br />public static final byte ZHAOYUN = (byte) ′f?//赵云的地图标?<br />public static final byte ZU = (byte) ′g?//卒的地图标记 <br />public static final byte BLANK = (byte) ′h?//I白的地图标?<br />public static final byte CURSOR = (byte) ′i?//光标的地图标?<br />//地图l合标记帔R <br />public static final byte DLEFT = (byte) ?? QA href="file://l?Qfile://l</AQ合囑Ş左边标记 <br />public static final byte DUP = (byte) ?? QA href="file://l?Qfile://l</AQ合囑Ş上边标记 <br />public static final byte DLEFTUP = (byte) ?? QA href="file://l?Qfile://l</AQ合囑Ş左上标记 <br />//囄帔R <br />public static Image image_base;//基本囄 <br />public static Image image_Zhaoyun;//赵云的图?<br />public static Image image_Caocao;//Ҏ(gu)的图?<br />public static Image image_Huangzhong;//黄忠的图?<br />public static Image image_Machao;//马超的图?<br />public static Image image_Guanyu;//关羽的图?<br />public static Image image_Zhangfei;//张飞的图?<br />public static Image image_Zu;//卒的囄 <br />public static Image image_Blank;//I白的图?<br />public static Image image_Frame;//游戏框架的图?<br />public Images() {//构造函?<br />} <br />public static boolean init() {//初始化游戏中用到的图?<br />try { <br />image_base = Image.createImage("/huarongroad/BITBACK.png"); <br />image_Frame = Image.createImage(image_base, 126, 0, 145, 177, <br />Sprite.TRANS_NONE); <br />//SpritecL用来{囄的,是MIDP2.0新新增加的支持游戏的Ҏ(gu)?<br />image_Zhaoyun = Image.createImage(image_base, 0, 0, UNIT, 2 * UNIT, <br />Sprite.TRANS_NONE); <br />image_Caocao = Image.createImage(image_base, UNIT, 0, 2 * UNIT, <br />2 * UNIT, Sprite.TRANS_NONE); <br />image_Huangzhong = Image.createImage(image_base, 3 * UNIT, 0, UNIT, <br />2 * UNIT, <br />Sprite.TRANS_NONE); <br />image_Machao = Image.createImage(image_base, 0, 2 * UNIT, UNIT, <br />2 * UNIT, <br />Sprite.TRANS_NONE); <br />image_Guanyu = Image.createImage(image_base, UNIT, 2 * UNIT, <br />2 * UNIT, UNIT, <br />Sprite.TRANS_NONE); <br />image_Zhangfei = Image.createImage(image_base, 3 * UNIT, 2 * UNIT, <br />UNIT, 2 * UNIT, <br />Sprite.TRANS_NONE); <br />image_Zu = Image.createImage(image_base, 0, 4 * UNIT, UNIT, UNIT, <br />Sprite.TRANS_NONE); <br />image_Blank = Image.createImage(image_base, 1 * UNIT, 4 * UNIT,UNIT, <br />UNIT, <br />Sprite.TRANS_NONE); <br />return true; <br />}catch (Exception ex) { <br />return false; <br />} <br />} <br />}<br /> (tng)</p> <p> (tng)</p> <p>Drawcȝ源代码如下:(x) </p> <p> <br />package huarongroad; <br />import javax.microedition.lcdui.*; <br />public class Draw { <br />//l制游戏中的囄 <br />public Draw(Canvas canvas) {//构造函?<br />} <br />public static boolean paint(Graphics g, byte img, int x, int y) { <br />//在地囄x,y点绘制img指定的图?<br />try { <br />paint(g, img, x, y, Images.UNIT);//把地图x,y点{化成d的绝对坐标,l图 <br />return true; <br />} <br />catch (Exception ex) { <br />return false; <br />} <br />} <br />public static boolean paint(Graphics g, byte img, int x, int y, int unit) { <br />try { <br />switch (img) { <br />case Images.CAOCAO://L?<br />//变成l对坐标Qƈ做调?<br />g.drawImage(Images.image_Caocao, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.GUANYU://d?<br />g.drawImage(Images.image_Guanyu, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.HUANGZHONG://画黄?<br />g.drawImage(Images.image_Huangzhong, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.MACHAO://画马?<br />g.drawImage(Images.image_Machao, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.ZHANGFEI://d?<br />g.drawImage(Images.image_Zhangfei, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.ZHAOYUN://画n?<br />g.drawImage(Images.image_Zhaoyun, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.ZU://d <br />g.drawImage(Images.image_Zu, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.BLANK://ȝ?<br />g.drawImage(Images.image_Blank, Images.LEFT + x * unit, <br />Images.TOP + y * unit, <br />Graphics.TOP | Graphics.LEFT); <br />break; <br />case Images.CURSOR://d?<br />g.drawRect(Images.LEFT + x * unit, <br />Images.TOP + y * unit,Images.UNIT,Images.UNIT); <br />break; <br />} <br />return true; <br />}catch (Exception ex) { <br />return false; <br />} <br />} <br />}<br /> (tng)</p> <p> (tng)</p> <p>其中Imagescd的是l图位置帔RQ也是在画图时每个格子的长度和相对坐标原点位置要进行的调整Q、地图位|常量(地图的长、宽Q,地图标记帔RQh物对应的记号Q,地图l合标记帔RQ后面会(x)l说Q,囄帔RQ存放h物的囄Q;DrawcM要负责在制定的位|画Zh物图片。下面我来说说ImagescM的地图标记常量和地图l合标记帔R。ؓ(f)?jin)能够灵zȝ安排各个关面的布局Q我们决定把游戏布局的信息存储在外部文g中,然后E序启动后把它读q来?</p> <p>q样我们制定?jin)一套存储图片的代码Q这是地图标记帔RQ如上面ImagescM定义的Caocao(Ҏ(gu))用a字符来表C,当程序读到a字符时就能将它{化成Ҏ(gu)对应的图片,q在da字符的位|上q行昄。但是从实际观察中我们发现所有的囄q不是统一大小的,有的?个格子,有的?个格子,q有的占1个格子,而且即便同是占两个格子的囄q有横、竖之分。有鉴于此,我们引入?jin)地囄合标记常量,是说在遇到占有多个格子的时候,?(也就是Images.LEFT)表示它的左边是一个真正的地图标记Q?(也就是Images.UP)表示它的上边是一个真正的地图标记Q?(也就是Images.LEFTUP)表示它的左上Ҏ(gu)一个真正的地图标记。地囄合标记常量其实就是用来占位置的,与实际显C无养I当后面我们将到移动时q(sh)(x)再来分析l合标记的用?</p> <p>DrawcM要是用来在画布上d囑ŞQ它有两个paintҎ(gu)Q这是很常见的函数重载。但是程序中实际上只用到?个参数的paintҎ(gu)Q它直接获得要画囄的相对坐标位|信息,然后调用5个参数的paintҎ(gu)?个参数的paintҎ(gu)相对坐标位|信息{换成l对位置Qƈ实际调用Graphics.drawImage()Ҏ(gu)Q将Images中的囄M(jin)出来。这U实现方法的好处是灵zd便于扩展Q但你需要画囄位置q不能够对应到格子中的相对坐标位|时Q你可以直接调?个参数的paintҎ(gu)Q而不必再M改这各类Q但你添加新的图片时Q只要在Images中增加对应的帔RQ然后向Draw?个参数的paintҎ(gu)d一条处理就可以?jin)。写到这里,两天的时间刚好用完?</p> <p>三、需求分?</p> <p>q部分叫做需求分析,听v来挺吓h的,其实是搞清楚我们要做什么,做成什么样Q那些不做。下面我引领着大家共同来完成这一步骤。首先,我们要做一个华定w的游戏,华容道的故事q里不再赘述?jin),但其中的人物在这里限定一下,如上面Imagesc里的定义,我们q个版本只提供曹?Caocao)、关?Guanyu)、张?Zhangfei)、n?Zhaoyun)、黄?Huangzhong)、马?Machao)和卒(Zu)。我们这里也限定一下游戏的操作Ҏ(gu)Q首先要通过方向键选择一个要Ud的区?是一张图?Q被选择的区域用黑色Ҏ(gu)框住Q选好后按Fire?是定?这块区域选中Q被选中的区域用l色Ҏ(gu)框住Q然后选择要移动到的区域,此时用红色方框框住被选择的区域;选好要移动到的区域之后按Fire键将要移动的区域(囄)Ud要移动到的区域,q去掉绿色和U色的方框。这里需要强调的概念有选择的区域、选中的区域、要Ud的区域和要移动到的区域,q四个概念请读者注意区分,当然也应当把q一部分记入数据字典之中?</p> <p>Z(jin)使文章的重点H出(介绍如何制作一个J2ME的收集游?Q我们这里限定一些与本主题无关的内容暂不d玎ͼ(x)q关之后的动?实现时要用到TimerTask或Threadc,后箋(hu)的系列文章中我会(x)详细介绍动画斚w的知?、关面之间的切换(其实很简单,当完成Q务之后重新再做一?、暂停和保存{操?q部分的内容介绍的资料很多,我也写不Z么新的东东来Q难免抄袭,故此免掉)?</p> <p>需求分析基本完成,M午还有一D|_(d)马上动手用ACDSee把从|上找来的BMP文gQ调整其大小?71*177(我的q个囄是两个部分合在一P所以比手机实际屏幕大了(jin))Q另存(sh)ؓ(f)PNG格式。半天时间刚刚好Q不但搞清楚?jin)要做的东东Q还把要用的囄准备好了(jin)?</p> <p>四、概要设?</p> <p>概要设计是从需求分析过渡到详细设计的桥梁和U带Q这一部分中我们确定项目的实现Ҏ(gu)和模块的划分。我们决定将整个目分成五个部分Q分别是前面介绍的Images、DrawQ还有Map和Displayable1和MIDlet1。Images和Drawcd能简单、结构固定,因此很多目我们都用这两各c,q里直接拿来Ҏ(gu)p用了(jin)Q前面已l介l过q里不再赘述。MapcL用来从外部文件读入地图,然后保存在一个数l之中,q部分的内容是我们在本阶D讨论的重点。Displayable1是一个承了(jin)CanvascȝdQ它用来处理E序的主要控刉辑和一部分控制逻辑所需的辅助函敎ͼ主要函数应该包括用来l图的paint()函数、用来控制操作的keyPressed()函数、用来控刉择区域的setRange()函数、用来控刉择要移动到区域的setMoveRange()函数、用来移动选中区域的Move()函数和判断是否完成Q务的win()函数Q更具体的分析,我们攑ֈ详细设计中去l化。MIDlet1实际上就是一个控制整个J2ME应用的控制程序,其实也没有什么可特别的,它和我们前面介绍?Hello World"E序大同异Q这里就不展开来说?jin),后面会(x)?chung)出它的全部代码?</p> <p>MapcM要应该有一个Grid[][]的二l数l,用来存放华容道的地图Q还应该有一个read_map()函数用来从外部文件读取地囑ֆ容填充Grid数据l构Q再是要有一个draw_map()函数用来把Grid数据l构中的地图内容转换成图片显C出?当然要调用DrawcȝpaintҎ(gu))。说到读取外部文ӞW者知道有两种Ҏ(gu)Q一U是传统的定义一个InputStream对象Q然后用getClass().getResourceAsStream()Ҏ(gu)取得输入,然后再从输入中取得外部文g的内容,例如 </p> <p> <br />InputStream is = getClass().getResourceAsStream("/filename"); <br />if (is != null) { <br />byte a = (byte) is.read(); <br />}<br /> (tng)</p> <p> (tng)</p> <p>q里h意文件名中的根\径是相对于便以后的class文g攄的位|,而不是源文g(java)。第二种Ҏ(gu)是用onnector.openInputStreamҎ(gu)Q然后打开的协议是ResourceQ但是这U方法笔者反复尝试都没能调通,报告的错误是~少Resource协议Q估计第二种Ҏ(gu)用到J2ME的某些扩展类包,此处不再q。由于以前已l做q一些类似华定wq样的地图,q里直接l出Mapcȝ代码Q后面就不再详细解释MapcM(jin)Q以便于我们可以集中_֊处理Displayable1中的逻辑?</p> <p>Mapcȝ代码如下Q?</p> <p> <br />package huarongroad; <br />import java.io.InputStream; <br />import javax.microedition.lcdui.*; <br />public class Map { <br />//处理游戏的地图,负责从外部文件加载地图数据,存放地图数据Qƈ按照地图数据l制地图 <br />public byte Grid[][];//存放地图数据 <br />public Map() {//构造函敎ͼ负责初始化地图数据的存储l构 <br />this.Grid = new byte[Images.HEIGHT][Images.WIDTH]; <br />//用二l数l存攑֜图数据,注意W一l是竖直坐标Q第二维是水q_?<br />} <br />public int[] read_map(int i) { <br />QA href="file://?Qfile://从</AQ外部文件加载地图数据,q存攑֜存储l构中,q回值是光标点的位置 <br />//参数是加载地图文件的{ <br />int[] a = new int[2];//光标点的位置Q?是水q位|,1是竖直位|?<br />try { <br />InputStream is = getClass().getResourceAsStream( <br />"/huarongroad/level".concat(String.valueOf(i))); <br />if (is != null) { <br />for (int k = 0; k Q?Images.HEIGHT; k++) { <br />for (int j = 0; j Q?Images.WIDTH; j++) { <br />this.Grid[k][j] = (byte) is.read(); <br />if ( this.Grid[k][j] == Images.CURSOR ) { <br />//判断出光标所在位|?<br />a[0] = j;//光标水^位置 <br />a[1] = k;//光标竖直位置 <br />this.Grid[k][j] = Images.BLANK;//光标位|设成空白背?<br />} <br />} <br />is.read();//d回RQ?3Q?忽略?<br />is.read();//d换行Q?0Q?忽略?<br />} <br />is.close(); <br />}else { <br />//d文gp| <br />a[0] = -1; <br />a[1] = -1; <br />} <br />}catch (Exception ex) { <br />//打开文gp| <br />a[0] = -1; <br />a[1] = -1; <br />} <br />return a; <br />} <br />public boolean draw_map(Graphics g) { <br />//调用Drawcȝ?rn)态方法,l制地图 <br />try { <br />for (int i = 0; i Q?Images.HEIGHT; i++) { <br />for (int j = 0; j Q?Images.WIDTH; j++) { <br />Draw.paint(g, this.Grid[i][j], j, i);//l制地图 <br />} <br />} <br />return true; <br />}catch (Exception ex) { <br />return false; <br />} <br />} <br />}<br /> (tng)</p> <p> (tng)</p> <p>对于像华定wq样的小型地囑֏以直接用手工来绘制地囄内容Q比如:(x) </p> <p>fa1c </p> <p>2232 </p> <p>bd1e </p> <p>2gg2 </p> <p>gihg </p> <p>但是Q如果遇到像坦克大战或超U玛莉那L(fng)地图Q就必须另外开发一个地囄辑器?我会(x)在后l的文章中介l用vb来开发一个地囄辑器)?</p> <p>五、详l设?</p> <p>详细设计是程序开发过E中臛_重要的一个环节,好在我们在前面的各个阶段中已l搭建好?jin)项目所需的一些工P现在q个阶段中我们只需集中_֊设计好Displayable1中的逻辑?两天的时间当然不只干q点z,q要把其他几个类的设计修改一? </p> <p>Displayable1q个c负责处理程序的控制逻辑。首先,它需要有表示当前关面的变量level、表C当前光标位|的变量loc、表CUd区域的变量SelectArea、表CUd到的区域的变量MoveArea、表C是否已有区域被选中而准备移动的变量Selected和Mapcȝ实例MyMap。然后,我们Ҏ(gu)用户按不同的键来处理不同的消息,我们要实现keyPressed()函数Q在函数中我们处理按键的上下左右和选中(Fire)Q这里的处理需要我展开来讲一Ԍ后面我很快会(x)把这一部分详细展开?</p> <p>接下来,是实现paint()函数Q我们打在q一部分中反复的重画背景、地囑֒选择区域Q这个函数必d理好区域被选中之后的画W颜色的切换Q具体讲是在没有选中M区域时要用黑色画W,当选重要移动的区域时用绿色画W,当选择要移动到的区域时改用U色ȝ(当然附加一张流E图是必不可的)?</p> <p>再下面要实现的setRange()函数和setMoveRange()函数Q这两个函数用来讄要移动的区域和要Ud到的区域Q我的思\是利用前面在ImagescM介绍q的地图l合标记帔RQ当Ud到地囄合标记常量时Q根据该点地图中的值做逆向变换扑ֈ相应的地图标记常量,然后讄相应的loc、SelectArea和MoveArea,其中setMoveRange()函数q用C(jin)一个辅助函数isInRange(),isInRange()函数是用来判断给定的Ҏ(gu)否在已选中的要Ud的区域之?如果isInRange()的返回值是假ƈ且该点处的g是空白就表明要移动到的区域R犯了(jin)其他以被占用的区域。有?jin)setRange()和setMoveRange()函数QMove()函数水到渠成了(jin),Move()函数要Ud的区域移动到要移动到的区?在移动过E中分ؓ(f)三步q行: </p> <p>W一.复制要移动的区域Q?</p> <p>W二.复制出的要Ud区域复制到要Ud到的区域(q两步分开q行的目的是防止在复制过E中覆盖掉要Ud的区?Q?</p> <p>W三.用isInRange2()判断l定的点是否在要Ud到的区域?不在要Ud到的区域内的点设|成I白?下面我们详细的分析一下keyPressed()函数的实现方?首先,keyPressed()函数要处理按键的上下左右和选中(Fire),在处理时需要用CanvascȝgetGameAction函数来将按键的键D{换成游戏的方?q样可以提高游戏的兼Ҏ(gu)?因ؓ(f)不同的J2ME实现,其方向键的键g一定是相同??</p> <p>接下?分别处理四个方向和选中.当按下向上时,先判断是否已l选定?jin)要Ud的区?即this.selected是否为真),如果没有选中要移动区域则让光标向上移动一?然后调用setRange()函数讄选择要移动的区域,再调用repaint()函数h屏幕,否则如果已经选中?jin)要Ud的区?p光标向上Ud一?然后调用setMoveRange()函数判断是否能够向上Ud已选中的区?如果能移动就调用repaint()函数h屏幕,如果不能Udp光标向下退回到原来的位|?</p> <p>当按下向下时,先判断是否已l选定?jin)要Ud的区?如果没有选中要移动的区域则判断当前所处的区域是否Z个格?如果是两个格高则向下Ud两格,如果是一个格高则向下Ud一?接着再调用setRange()函数讄选择要移动的区域,而后调用repaint()函数h屏幕,否则如果已经选中?jin)要Ud的区?p光标向下Ud一?然后调用setMoveRange()函数判断是否能够向下Ud已选中的区?如果能移动就调用repaint()函数h屏幕,如果不能Udp光标向上退回到原来的位|?按下向左时情况完全类似向上的情况,按下向右时情况完全类似向下的情况,因此q里不再赘述,详细情况请参见程序的源代码?</p> <p>当按下选中键时,先判断是否已l选中?jin)要Ud的区?如果已经选中?jin)要Ud的区域就调用Move()函数完成pUd的区域到要移动到的区域的Udq程,接着调用repaint()函数h屏幕,然后已选择标记|成false,l箋(hu)调用win()函数判断是否完成?jin)Q?否则如果q没有选定要移动的区域则再判断当前选中区域是否为空?如果不是I白将选中标记|成true,然后h屏幕.q里介绍一个技?在开发程序遇到复杂的逻辑的时?可以构造一格打印函数来所兛_(j)的数据结构打印出来以利调?q里我们构造一个PrintGrid()函数,q个函数Ua(b)是ؓ(f)?jin)调试之?效果q得不错.x(chng)我们完成?jin)编码前的全部工作?</p> <p>六、编?</p> <p>整个目共有五个c?有四个类的代码前面已l介l过?而且是在其他目中用过的相Ҏ(gu)熟的代码.现在只需全力d现Displayable1c?Displayable1cȝ代码如下: </p> <p> <br />package huarongroad; <br />import javax.microedition.lcdui.*; <br />public class Displayable1 extends Canvas implements CommandListener { <br />private int[] loc = new int[2]; QA href="file://?Qfile://光</AQ标的当前位|,0是水q位|,1是竖直位|?<br />private int[] SelectArea = new int[4];//被选定的区域,卌Ud的区?<br />private int[] MoveArea = new int[4];//要移动到的区?<br />private Map MyMap = new Map();//地图c?<br />private boolean selected;//是否已经选中要移动区域的标志 <br />private int level;//但前的关?<br />public Displayable1() {//构造函?<br />try { <br />jbInit();//JBuilder定义的初始化函数 <br />}catch (Exception e) { <br />e.printStackTrace(); <br />} <br />} <br />private void Init_game(){ <br />//初始化游戏,d地图Q设|选择区域Q清IUd到的区域 <br />this.loc = MyMap.read_map(this.level);//d地图文gQƈq回光标的初始位|?<br />//0为水q位|,1为竖直位|?<br />this.SelectArea[0] = this.loc[0];//初始化选中的区?<br />this.SelectArea[1] = this.loc[1]; <br />this.SelectArea[2] = 1; <br />this.SelectArea[3] = 1; <br />this.MoveArea[0] = -1;//初始化要Ud到的区域 <br />this.MoveArea[1] = -1; <br />this.MoveArea[2] = 0; <br />this.MoveArea[3] = 0; <br />} <br />private void jbInit() throws Exception {//JBuilder定义的初始化函数 <br />QA href="file://?Qfile://初</AQ始化实例变?<br />this.selected = false;//讄没有被选中的要Ud区域 <br />this.level = 1; <br />Images.init();//初始化图片常?<br />Init_game();//初始化游戏,d地图Q设|选择区域Q清IUd到的区域 <br />setCommandListener(this);//d命o(h)监听Q这是Displayable的实例方?<br />addCommand(new Command("Exit", Command.EXIT, 1));//d“退出”按?<br />} <br />public void commandAction(Command command, Displayable displayable) { <br />//命o(h)处理函数 <br />if (command.getCommandType() == Command.EXIT) {//处理“退出?<br />MIDlet1.quitApp(); <br />} <br />} <br />protected void paint(Graphics g) { <br />//d函数Q用于绘制用L(fng)面,x(chng)C图片,勄选中区域和要Ud到的区域 <br />try { <br />g.drawImage(Images.image_Frame, 0, 0, <br />Graphics.TOP | Graphics.LEFT);//画背?<br />MyMap.draw_map(g);//按照地图内容d <br />if ( this.selected ) <br />g.setColor(0,255,0);//如果被选中Q改用绿色画?gu)选中的区?<br />g.drawRect(this.SelectArea[0] * Images.UNIT + Images.LEFT, <br />this.SelectArea[1] * Images.UNIT + Images.TOP, <br />this.SelectArea[2] * Images.UNIT, <br />this.SelectArea[3] * Images.UNIT);//d选择区域Q?<br />QA href="file://?Qfile://如</AQ果被选中Q就用绿?<br />QA href="file://?Qfile://否</AQ则Q用黑?<br />g.setColor(255,255,255);//恢复ȝ颜色 <br />if (this.selected) {//已经选中?jin)要Ud的区?<br />g.setColor(255, 0, 255);//改用U色 <br />g.drawRect(this.MoveArea[0] * Images.UNIT + Images.LEFT, <br />this.MoveArea[1] * Images.UNIT + Images.TOP, <br />this.MoveArea[2] * Images.UNIT, <br />this.MoveArea[3] * Images.UNIT);//d要移动到的区?<br />g.setColor(255, 255, 255);//恢复ȝ颜色 <br />} <br />}catch (Exception ex) { <br />} <br />System.out.println(Runtime.getRuntime().freeMemory()); <br />System.out.println(Runtime.getRuntime().totalMemory()); <br />} <br />private void setRange() { <br />//讄Ud后能够选中的区?<br />//调整当前光标位置到地囄M|,卌录h物信息的位置 <br />if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DLEFT) { <br />this.loc[0] -= 1;//向左?<br />}else if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DUP) { <br />this.loc[1] -= 1;//向上?<br />}else if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DLEFTUP) { <br />this.loc[0] -= 1;//向左?<br />this.loc[1] -= 1;//向上?<br />} <br />this.SelectArea[0] = this.loc[0];//讄光标的水q位|?<br />this.SelectArea[1] = this.loc[1];//讄光标的竖直位|?<br />//讄光标的宽?<br />if (this.loc[0] + 1 Q?Images.WIDTH) { <br />this.SelectArea[2] = this.MyMap.Grid[this.loc[1]][this.loc[0] + 1] != (byte) ??? <br />1 : 2; <br />}else { <br />this.SelectArea[2] = 1; <br />} <br />//讄光标的高?<br />if (this.loc[1] + 1 Q?Images.HEIGHT) { <br />this.SelectArea[3] = this.MyMap.Grid[this.loc[1] + 1][this.loc[0]] != (byte) ??? <br />1 : 2; <br />}else { <br />this.SelectArea[3] = 1; <br />} <br />} <br />private boolean setMoveRange() { <br />//讄要移动到的区域,能够Udq回true,否则q回false <br />for (int i = 0; i Q?this.SelectArea[2]; i++) { <br />for (int j = 0; j Q?this.SelectArea[3]; j++) { <br />if (this.loc[1] + j Q? Images.HEIGHT || <br />this.loc[0] + i Q? Images.WIDTH || <br />(!isInRange(this.loc[0] + i, this.loc[1] + j) && <br />this.MyMap.Grid[this.loc[1] + j][this.loc[0] + i] != <br />Images.BLANK)) { <br />return false; <br />} <br />} <br />} <br />this.MoveArea[0] = this.loc[0]; <br />this.MoveArea[1] = this.loc[1]; <br />this.MoveArea[2] = this.SelectArea[2]; <br />this.MoveArea[3] = this.SelectArea[3]; <br />return true; <br />} <br />private boolean isInRange(int x, int y) { <br />//判断l定的(xQyQ点是否在选定区域之内Qx是水q_标,y是竖直坐?<br />if (x Q? this.SelectArea[0] && <br />x Q?this.SelectArea[0] + this.SelectArea[2] && <br />y Q? this.SelectArea[1] && <br />y Q?this.SelectArea[1] + this.SelectArea[3]) { <br />return true; <br />}else { <br />return false; <br />} <br />} <br />private boolean isInRange2(int x, int y) { <br />//判断l定的(xQyQ点是否在要Ud到的区域之内Qx是水q_标,y是竖直坐?<br />if (x Q? this.MoveArea[0] && <br />x Q?this.MoveArea[0] + this.MoveArea[2] && <br />y Q? this.MoveArea[1] && <br />y Q?this.MoveArea[1] + this.MoveArea[3]) { <br />return true; <br />}else { <br />return false; <br />} <br />} <br />protected void keyPressed(int keyCode) { <br />//处理按下键盘的事Ӟq是Canvas的实例方?<br />switch (getGameAction(keyCode)) {//按键的D{化成方向帔R <br />case Canvas.UP://向上 <br />if (!this.selected) {//q没有选定要移动的区域 <br />if (this.loc[1] - 1 Q? 0) {//向上q有UdI间 <br />this.loc[1]--;//向上Ud一?<br />setRange();//讄光标Ud的区域,该函数能光标移动到地图M|?<br />repaint();//重新l图 <br />} <br />}else {//已经选定?jin)要Ud的区?<br />if (this.loc[1] - 1 Q? 0) {//向上q有UdI间 <br />this.loc[1]--;//向上Ud一?<br />if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?<br />repaint();//重新l图 <br />}else {//不能Ud <br />this.loc[1]++;//退回来 <br />} <br />} <br />} <br />break; <br />case Canvas.DOWN://向下 <br />if (!this.selected) {//q没有选定要移动的区域 <br />if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有UdI间 <br />if (this.MyMap.Grid[this.loc[1] + 1][this.loc[0]] == <br />Images.DUP){//该图片有两个格高 <br />this.loc[1]++;//向下Ud一?<br />if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有 <br />QA href="file://U?Qfile://U</AQ动I间 <br />this.loc[1]++;//向下Ud一?<br />setRange();//讄光标Ud的区域, <br />QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?<br />repaint();//重新l图 <br />}else {//向下没有UdI间 <br />this.loc[1]--;//退回来 <br />} <br />}else {//该图片只有一个格?<br />this.loc[1]++;//向下Ud一?<br />setRange();//讄光标Ud的区域, <br />QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?<br />repaint();//重新l图 <br />} <br />}else { <br />} <br />}else {//已经选定?jin)要Ud的区?<br />if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有UdI间 <br />this.loc[1]++;//向下Ud一?<br />if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?<br />repaint();//重新l图 <br />}else {//不能Ud <br />this.loc[1]--;//退回来 <br />} <br />} <br />} <br />break; <br />case Canvas.LEFT://向左 <br />if (!this.selected) {//q没有选定要移动的区域 <br />if (this.loc[0] - 1 Q? 0) {//向左q有UdI间 <br />this.loc[0]--;//向左Ud一?<br />setRange();//讄光标Ud的区域,该函数能光标移动到地图M|?<br />repaint();//重新l图 <br />} <br />}else {//已经选定?jin)要Ud的区?<br />if (this.loc[0] - 1 Q? 0) {//向左q有UdI间 <br />this.loc[0]--;//向左Ud一?<br />if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?<br />repaint();//重新l图 <br />}else {//不能Ud <br />this.loc[0]++;//退回来 <br />} <br />} <br />} <br />break; <br />case Canvas.RIGHT://向右 <br />if (!this.selected) {//q没有选定要移动的区域 <br />if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有UdI间 <br />if (this.MyMap.Grid[this.loc[1]][this.loc[0] + 1] == <br />Images.DLEFT) {//该图片有两个格宽 <br />this.loc[0]++;//向右Ud一?<br />if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有 <br />QA href="file://U?Qfile://U</AQ动I间 <br />this.loc[0]++;//向右Ud一?<br />setRange();//讄光标Ud的区域, <br />QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?<br />repaint();//重新l图 <br />}else {//向右没有UdI间 <br />this.loc[0]--;//退回来 <br />} <br />}else {//该图片只有一个格?<br />this.loc[0]++;//向右Ud一?<br />setRange();//讄光标Ud的区域, <br />QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?<br />repaint();//重新l图 <br />} <br />}else { <br />} <br />}else {//已经选定?jin)要Ud的区?<br />if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有UdI间 <br />this.loc[0]++;//向右Ud一?<br />if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?<br />repaint();//重新l图 <br />}else {//不能Ud <br />this.loc[0]--;//退回来 <br />} <br />} <br />} <br />break; <br />case Canvas.FIRE: <br />if (this.selected) {//已经选定?jin)要Ud的区?<br />Move();//要Ud的区域移动到刚选中的区?<br />repaint();//重新l图 <br />this.selected = false;//清除已选定要移动区域的标志 <br />if ( win()) { <br />System.out.println("win"); <br />} <br />}else {//q没有选定要移动的区域 <br />if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == <br />Images.BLANK) {//要移到的位置是一个空?<br />}else {//要移到的位置不是I白 <br />this.selected = true;//讄已选定要移动区域的标志 <br />} <br />repaint();//重新l图 <br />} <br />break; <br />} <br />} <br />private boolean win(){ <br />QA href="file://?Qfile://判</AQ断是否已经救出?jin)曹?<br />if ( this.MyMap.Grid[Images.HEIGHT - 2 ][Images.WIDTH - 3 ] == Images.CAOCAO ) <br />return true; <br />else <br />return false; <br />} <br />private void PrintGrid(String a) { <br />QA href="file://?Qfile://打</AQ印当前地图的内容,用于调试 <br />System.out.println(a); <br />for (int i = 0; i Q?Images.HEIGHT; i++) { <br />for (int j = 0; j Q?Images.WIDTH; j++) { <br />System.out.print( (char)this.MyMap.Grid[i][j]); <br />} <br />System.out.println(""); <br />} <br />} <br />private void Move() { <br />QA href="file://?Qfile://</AQ要Ud的区域移动到刚选中的区?<br />if (this.MoveArea[0] == -1 || this.MoveArea[1] == -1 || <br />this.SelectArea[0] == -1 || this.SelectArea[1] == -1) {//没有选中区域 <br />}else {//已经选中?jin)要Ud的区域和要移动到的区?<br />byte[][] temp = new byte[this.SelectArea[3]][this.SelectArea[2]]; <br />QA href="file://?Qfile://复</AQ制要移动的区域Q因块区域可能会(x)被覆盖掉 <br />for (int i = 0; i Q?this.SelectArea[2]; i++) { <br />for (int j = 0; j Q?this.SelectArea[3]; j++) { <br />temp[j][i] = <br />this.MyMap.Grid[this.SelectArea[1] +j] <br />[this.SelectArea[0] + i]; <br />} <br />} <br />QA href="<a href="file://PrintGrid/">file://PrintGrid</a>"Q?a href="file://PrintGrid/">file://PrintGrid</a>Q?AQ?"1"); // 调试信息 <br />QA href="file://?Qfile://</AQ要Ud的区域移动到刚选中的区域(卌Ud到的区域Q?<br />for (int i = 0; i Q?this.SelectArea[2]; i++) { <br />for (int j = 0; j Q?this.SelectArea[3]; j++) { <br />this.MyMap.Grid[this.MoveArea[1] + j] <br />[this.MoveArea[0] + i] = temp[j][i]; <br />} <br />} <br />QA href="<a href="file://PrintGrid/">file://PrintGrid</a>"Q?a href="file://PrintGrid/">file://PrintGrid</a>Q?AQ?"2");// 调试信息 <br />QA href="file://?Qfile://</AQ要Ud的区域中无用内容|成I白 <br />for (int i = 0; i Q?this.SelectArea[3]; i++) { <br />for (int j = 0; j Q?this.SelectArea[2]; j++) { <br />if (!isInRange2(this.SelectArea[0] + j, <br />this.SelectArea[1] + i)) {//该点是不在要Ud?<br />QA href="file://?Qfile://的</AQ区域之内,需|空 <br />this.MyMap.Grid[this.SelectArea[1] + i] <br />[this.SelectArea[0] + j] = Images.BLANK; <br />}else { <br />} <br />} <br />} <br />QA href="<a href="file://PrintGrid/">file://PrintGrid</a>"Q?a href="file://PrintGrid/">file://PrintGrid</a>Q?AQ?"3");// 调试信息 <br />this.SelectArea[0] = this.MoveArea[0];//重置选中位置的水q_?<br />this.SelectArea[1] = this.MoveArea[1];//重置选中位置的竖直坐?<br />this.MoveArea[0] = -1;//清空要移动到的位|?<br />this.MoveArea[1] = -1;//清空要移动到的位|?<br />this.MoveArea[2] = 0;//清空要移动到的位|?<br />this.MoveArea[3] = 0;//清空要移动到的位|?<br />} <br />} <br />}<br /> (tng)</p> <p> (tng)</p> <p>代码的相兛_?在详l设计阶D已l讲q?代码中有比较相近的注?误者自行研d?全部的代码写好,用wtk2.0自带的Ktoolbar工具建立一个工E?接下来把M源文件放到正位|下,然后点击build,再点run,完成了(jin)E序的编?当然如果有错误还要修改和调试?</p> <p>七、测?</p> <p>作ؓ(f)一个真正的产品要经q单体测试、结合测试和pȝ试。由于项目本w简?而且大部分代码已l是相对成熟?我们跌单体试Q又׃W者的实际环境所?无法搞到Java手机,无法架设OTA服务?因此我们也只能放弃系l测试。那么就让我们开始结合测试吧。测试之前要先出一个测试式样书,也就是测试的计划。我们将它简化一?只测试如下几U情?W一、对各种形状的区域的选择和移?W二、(f)q边界区域的选择和移?W三、同一区域的反复选择和反复移?W四、非法选择和非法移动。有?jin)测试的目?接下来的工作是用wtk2.0自带的Run MIDP Application工具q行试。打开q个工具,加蝲huarongRoad的jad文g,E序׃(x)自动q行,选择launch上MIDlet1q个E序,华容道游戏就?x)跃然屏q之?接下来的工作是左三?右三?拇指扭扭,来做试。测试过E中发现M的问?立刻发一个bug给自己,然后又是痛苦的调试和修正bug,如此如此?</p> <p>八、发?</p> <p>谈到发布,其实是个关键,再好的品不能很好的发布出去也只是个产品而已,变(sh)成商品也得不到回报.׃W者的条g所?q里只能是纸上谈?不过q是希望能够使读者对q一q程有所?jin)?|上的资料也很多)?</p> <p>J2ME的程序发布一般都是通过OTA(Over The Air),你只需要一台有公网IP的主机和一个普通的web Server可以了(jin)(管要求很低,但笔者还是没?Q这里我们以apacheZ介绍一下OTA服务的配|,首先是安装好?jin)apache服务器,然后在conf目录下找到mime.types文gQ在该文件中加入如下两行 </p> <p>application/java-archive jar </p> <p>text/vnd.sun.j2me.app-descriptor jad </p> <p>然后重vapache服务器就可以?jin)。接下来的工作就是修改jad文g中MIDlet-Jar-URL:后面的参敎ͼ它改ؓ(f)URL的绝对\径,卻IA href="<a href="http://***/">http://***/</a>"Q?a href="http://***/">http://***/</a>Q?AQhuarongroad.jar(其中***是你的域名或IP地址)。在下面是用java手机下蝲jad文gQ它?x)自动部|相应的jar文gq加载它。剩下的工作和在模拟器上操作是一L(fng)?jin)?</p> <p>?ji)、项目ȝ </p> <p>x(chng)Q我们已l完成了(jin)一个J2ME游戏的全部开发过E,E序中涉?qing)到了(jin)调研、分析、设计、编码、测试和发布{方面的问题Q其实在实际的工作中q有很多更ؓ(f)具体的问题,毕竟技术只在Y件开发过E中占据很有限的一部分Q这里限于篇q的限制无法一一具体展开。今后,W者计划再写一用J2ME开发手机屏保的文章Q借此Z(x)向读者展CJ2ME动画技术;然后再写一J2ME|络应用的文章,做一个类似开?j)辞兔RL(fng)知识问答游戏Q以便向读者展CJ2ME的网l技术;待这两方面的技术交待清楚之后,我将引领读者制作一个稍大一些的游戏?/p> <img src ="http://www.tkk7.com/zjw-albert/aggbug/57152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjw-albert/" target="_blank">zjw_albert</a> 2006-07-07 16:15 <a href="http://www.tkk7.com/zjw-albert/archive/2006/07/07/57152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2ME与MIDP开?/title><link>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57136.html</link><dc:creator>zjw_albert</dc:creator><author>zjw_albert</author><pubDate>Fri, 07 Jul 2006 06:59:00 GMT</pubDate><guid>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57136.html</guid><wfw:comment>http://www.tkk7.com/zjw-albert/comments/57136.html</wfw:comment><comments>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57136.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjw-albert/comments/commentRss/57136.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjw-albert/services/trackbacks/57136.html</trackback:ping><description><![CDATA[ <dt>Java嵌入式开发之? </dt> <dd class="ArticleInfo">2005.08.08 (tng) (tng)来自Q无U空闾b? </dd> <dd class="ArticleContent"> <table style="FLOAT: left; MARGIN: 0px 10px 10px" cellspacing="0" cellpadding="0" align="left" border="0"> <tbody> <tr> <td> <script type="text/javascript"> <!-- csdn_AD_Position_GroupID = "{e025b96b-2fda-4e82-84ef-3e0772838ed3}"; csdn_AD_Page_Url = document.location; csdn_AD_CurrPage_CharSet = "gb2312"; //--> </script> <script src="http://ggmm.csdn.net/AD/Show_JavaScript_AD.js" type="text/javascript"> </script> <script language="JavaScript1.1" src="http://ggmm.csdn.net/AD/ShowJavaScriptAD.aspx?show=true&position={e025b96b-2fda-4e82-84ef-3e0772838ed3}&CharSet=gb2312"> </script> <br /> <script src="http://news.csdn.net/ad/news_textlink.js" type="text/javascript"> </script> </td> </tr> </tbody> </table> <br /> <center> <b>J2ME与MIDP开?/b> </center> <br />在我前面的三文章中Q我介绍?jin)一些关于J2ME的基本的知识Q在q篇文章中我惌谈J2ME与MIDP开发的一些知识,其实在本pd的第二部分我门就已经接触到MIDP?jin),现在只是x(chng)入探讨一下。MIDP是Mobile Information Devices Profile(Ud信息讑֤?的简Uͼ而遵?MIDP和CLDC规范~写?Java应用E序我们q其ؓ(f) MIDlet?br /><br />  你可以从MIDPq个规范的英文名U的含义推测Q?MIDlet是定位于提供某种水^的网l连接性的Ud讑֤。运?MIDlet的设备也有好几个共同的属性:(x)有限的屏q大,内存和处理能?q个规范是设计来满q些需求,典型的设备包含行动电(sh)话和呼叫器?br /><br />  q篇文章重点介l安装和配置 CLDC?MIDP软g,我们也将写一个简单的 MIDletq学?fn)在一个移动设备预览这个MIDlet的必需的步骤,最后再谈一谈如何给MIDlet打包?br /><br />  CLDC定义?jin)一个用?Java虚拟机的规范和一l核?j)类库,CLDC本质上是一?Java 2标准?( J2SE )的简化版本,是ؓ(f)?jin)用有限内存和资源的设备设计的。配|?(比如 CLDC )是设计来q行表的Q而MID表是一个规范,它提供一套核?j)类库来~写那些用于Ud讑֤的Java应用E序。一个简表定义类库,开发者们使用q些cd来ؓ(f)某一特定的设备或用于某一范围的设备编写应用程序。例如, MIDP定义的类是用于创建用L(fng)?文本框、表单等)Q处理用戯入以?qing)?HTTP在一个网l上通讯?br /><br />  <b>W一节 开发MIDlet</b><br /><br />  <b>下蝲软g</b><br /><br />  在你能写一?MIDlet之前Q你需要下载必需的YӞ(x) JDKQCLDC以及(qing) MIDP?br />  · <a target="_blank"><font color="#000066">Java Development Kit ( JDK )</font></a>-- 1.2版本以上 <br /><br />  · <a target="_blank"><font color="#000066">Connected, Limited Device Configuration (CLDC)</font></a><br />  ·<a target="_blank"><font color="#000066"> Mobile Information Device Profile (MIDP)</font></a><br /><br />  你也可能选择下蝲 <a target="_blank"><font color="#000066">J2ME规范</font></a>Q下载到的这个规范包?MIDP应用E序接口Q当你是初次开?MIDletӞ它是一个非常好的参考?br /><br />  <b>安装软g</b><br /><br />  一、JDK<br /><br />  JDK已经默认?jin)用于安装文件的目录Q当然了(jin)Q你也可以选择安装在一个你自己选定的\径。如果安装的 JDK版本?1.3q且选择默认路径Q那?JDK被安装到这个目录:(x)c:jdk1.3<br /><br />  你一定很好奇Qؓ(f)什么需?JDKQ因?CLDC?MIDP安装好后都不包括Java~译E序 javac.exeQ很明显Q没有编译程序就没有能力~译你的 Java代码Q你也不可能有进步?br /><br />  二、有限连接设备配|?( CLDC )<br /><br />  解压你下载到盘?sh)?zip文gQ我推荐路径?C:j2me。解压以后,c:j2me路径的结构如下所C:(x)解压以后Qc:j2me路径的结构如下所C:(x)<br /><br />  c:j2me<br />  |<br />  j2me_cldc<br /><br />  三、移动信息设备简?( MIDP )<br /><br />  同上Q解压你下蝲到硬盘(sh)?zip文gQ用上面相同的目录C:j2meQ现在那个目录结构应该像Q?br /><br />  C:j2me<br />  |<br />  j2me_cldc<br />  midp-fcs<br /><br />  <b>配置软g</b><br /><br />  一、更?PATH<br /><br />  PATH环境变量?Windows操作pȝ使用来定位可执行E序的,我们需要更?PATH来指?Java~译E序?CLDC?MIDPE序的\径?br /><br />  Q?Q更?JDK的PATH<br /><br />  a、Windows 2000?Windows NTpȝ<br /><br />   · 从控刉板中选择pȝ<br /><br />   · 点击"高"Q再点击"环境变量"<br /><br />   · 扑ֈ PATHQ点入,在最后添加JDK安装路径?#x8;in目录Q假设你安装 JDK?1.3版本q择默认安装路径Q你添加:(x)C:jdk1.3<br /><br />  b、Windows 98?Windows 95<br /><br />  如果使用的是Windows 98?Windows 95pȝQ请在C盘跟目录下的Autoexec.bat文g的最后面加上以下两行Q? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>set path=c:jdk1.3in;%path%<br />set classpath=.;</td></tr></tbody></table><br />  Q?Q更?CLDC路径<br /><br />  你还需要更C的PATH环境变量来指向存?CLDC可执行文件的目录。按照上面概q的相同的步骤来d到PATH中:(x)<br /><br />  C:j2mej2me_cldcin<br /><br />  Q?Q更?MIDP路径<br /><br />  同上面那P更新 PATH环境来指出存?MIDP可执行文件的目录;q个文g是用于测试你?MIDlet的移动电(sh)话模拟器?br /><br />  按照上面概述的相同的步骤来添加到PATH中C:j2memidp-fcsin<br /><br />  二、更?CLASSPATH环境变量<br /><br />  CLASSPATH告诉 Java~译E序C么地Ҏ(gu)索那些不?JDKq_本n附带的类库,在本例中Q我们需要更?CLASSPATH来指向MIDPcR你q需要有当前目录的引?".")Q作为CLASSPATH的一部分Q按照上面概q的相同的步?更新CLASSPATH: CLASSPATH=C:j2memidp-fcsclasses;. - 注意最后的?."表示当前的工作目录?br /><br />  三、添加SCREEN_DEPTH环境变量<br /><br />  MIDP含有一个测?MIDlet用的Ud讑֤模拟器,q个模拟器可以以有色模式q行Q也可以q行于黑白两色构成的灰度梯度模式。ؓ(f)?jin)指定颜色数Q你可以d环境变量 SCREEN_DEPTH。例如:(x)<br /><br />  SCREEN_DEPTH=8<br /><br />  dq个环境变量的方法与处理 PATH?CLASSPATH变量的方法类伹{?br /><br />  SCREEN_DEPTH值和颜色对应? <table cellspacing="0" width="500" align="center" border="1"><tbody><tr><td>?/td><td>颜色?/td></tr><tr><td height="12">1 </td><td height="12">2 </td></tr><tr><td>2 </td><td>4 </td></tr><tr><td height="3">4 </td><td height="3">16 </td></tr><tr><td>8 </td><td>256</td></tr></tbody></table><br />  <b>试安装</b><br /><br />  在编写一?MIDlet之前Q让我们(g)查一下是否所有的软g都已正确地安装?br /><br />  1. q入命o(h)?br /><br />  2. 试CLDC安装Q键入preverifyq按回R键? <table width="500" align="center" border="0"><tbody><tr><td><a target="_blank"><img alt="" src="http://images.csdn.net/20050808/134a98ea-f15d-4fc7-962e-a1e4147137b3.gif" border="0" /></a><a target="_blank"></a></td></tr></tbody></table> 3. 试 MIDP安装Q键?midpq按回R键。应该弹Z个窗口,如下图所C:(x) <table width="164" align="center" border="0"><tbody><tr><td><a target="_blank"><img alt="" src="http://images.csdn.net/20050808/5762de42-42c0-4d60-9f7e-2d2bb89509a2.jpg" border="0" /></a></td></tr></tbody></table><br />  4. 试 JDK安装Q键?java -versionq按回R键,屏幕出C面的样子? <table width="500" align="center" border="0"><tbody><tr><td><a target="_blank"><img alt="" src="http://images.csdn.net/20050808/9d4fcc10-de01-4520-b313-e7760b985c22.gif" border="0" /></a></td></tr></tbody></table><br />  开发一个MIDletE序 <table width="500" align="center" border="0"><tbody><tr><td><a target="_blank"><img alt="" src="http://images.csdn.net/20050808/b03b0d7a-aa79-472a-86c9-86492e7b4761.jpg" border="0" /></a></td></tr></tbody></table><br />  在编写MIDletE序之前我还要再说两句,前面我也说过?jin)MIDPE序UCؓ(f)MIDletQ这可能因ؓ(f)所有的 MIDlet都是扩展 javax.microedition.midlet.MIDletc?(正象 Java applet扩展 AppletcM? 除了(jin)从键盘或点击讑֤上接受输入的信息以外Q?MIDLetc还提供用于ȀzR暂停和l结 MIDlet的接口,卛_别是startApp()、pauseApp()和destroyApp() Ҏ(gu)。startApp()Ҏ(gu)在概念上?Java applet?start()Ҏ(gu)cMQ当MIDlet启动时它被调用,而且在一个MIDlet暂停之后恢复时也被调用?br /><br />  另外一个值得注意的类是javax.microedition.lcdui.CommandcR这个类定义?jin)好几个Ud讑֤通常使用的语义类型:(x) BACK、CANCEL、EXIT、HELP、ITEM、MENU、OK、SCREEN和STOP。通过 javax.microedition.lcdui.Displayablec(所有的 J2ME UIlg的父c)(j)中的addCommand()Ҏ(gu)把这些命令添加到用户界面上。addCommand()Ҏ(gu)包括一个优先参数Q允许应用程序提C行时ȝ境应当按照什么顺序显CZ么内宏V在大多数环境中Q如果两个相同类型的命o(h)被用相同的优先U水qx(chng)加的话,环境?yu)显CZ个菜?" menu "选项q允许用户从多个命o(h)选项中选择?br /><br />  大家是不是心(j)里都痒痒的了(jin)Q好Q让我们开始编写一个非常简单的 MIDlet吧,q个 MIDlet创Z个带有一则消息的文本框。我们还要添加一个命令按钮用于退?gu)?MIDlet?br /><br />  <b>一、编?Java源代?/b><br /><br />  创徏一个新目录来保存(sh)以后~写的MIDletQ例?c:midletsQ在q个目录里再创徏一个叫myMIDlet的目录,使用M文本~辑器创Z个名?simpleMIDlet.java的文件ƈ输入下面q一D?Java源代码。把q个文g保存在c:midletsmyMIDlet目录 (或者Q何你选择的目??br />代码D? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>simpleMIDlet.java<br /><br />import javax.microedition.midlet.*;<br />import javax.microedition.lcdui.*;<br /><br />public class simpleMIDlet extends MIDlet implements CommandListener<br />{<br />private Display display; // 引用MIDlet的Display 对象<br />private TextBox tbxMain; // Textbox 昄一条消?br />private Command cmdExit; // 讑֮按钮用于退出MIDlet<br /><br />// MIDlet构造程?br />public simpleMIDlet()<br />{<br />display = Display.getDisplay(this);<br /><br />cmdExit = new Command("Exit", Command.SCREEN, 1);<br /><br />tbxMain = new TextBox("Simple MIDlet", "Welcome ", 50, 0);<br />tbxMain.addCommand(cmdExit);<br />tbxMain.setCommandListener(this);<br />}<br /><br />// 被应用程序管理器调用来启动MIDlet?br />public void startApp()<br />{<br />display.setCurrent(tbxMain);<br />}<br /><br />// 一个必要的Ҏ(gu)<br />public void pauseApp()<br />{ }<br /><br />file://一个必要的Ҏ(gu)<br />public void destroyApp(boolean unconditional)<br />{ }<br /><br />file://(g)查一下是否选择?jin)退出命?br />public void commandAction(Command c, Displayable s)<br />{<br />if (c == cmdExit)<br />{<br />destroyApp(false);<br />notifyDestroyed();<br />}<br />}<br />}</td></tr></tbody></table><br />  此时Q先不必担心(j)每行代码是做什么用的,把注意力攑֜开发这一整个环节中?br /><br />  <b>二、编译ƈ预验证(preverifyQ?/b><br /><br />  现在你必ȝ译这?java源文件ƈ?preverify生成?class文g?br /><br />  1.~译源代?br /><br />  q入命o(h)行Ş式,q入你保存文件的目目录Q用下面的命o(h)~译E序。用下面的命o(h)~译E序? <table width="579" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td height="21">avac -bootclasspath c:j2memidp-fcsclasses simpleMIDlet.java  </td></tr></tbody></table><br />  选项 - bootclasspath CQ?j2memidp - fcsclasses指定?Java自D(启动)cL件目录。我们必自己指向midpc,否则javac?x)用默认的JDKcdȝ译MIDletE序。不出问题的话,p利地编译simpleMIDlet.java生成simpleMIDlet.class文g (默认情况下,生成?class位于 Java源文件所在的目录Q?br /><br />  2.预验证类文g? <table width="557" align="center" border="0"><tbody><tr bgcolor="#ebe9eb"><td>preverify -classpath c:j2memidp-fcsclasses;. -d . simpleMIDlet</td></tr></tbody></table><br />  选项" -classpath C:j2memidp-fcsclasses;." 指定?jin)到哪里d扄于预验证?class文g。这包括需要用来做验证处理?MIDPc?(通过 c:j2memidp-fcsclasses指定 )和你的类文gQ它位于当前目录 (是"."指定??br /><br />  选项"-d." 告诉预验证器把验证过的类文g攑֜什么地斏V这一?." 指当前目录,卛_始的cL件相同的位置?br /><br />  注意Q前面的 preverify命o(h)行选项用一个新的、预验证q的cL件覆盖原先的cL件。你可以分两个目录,一个用来保存通过~译的类文gQ另一个用来保存通过预验证创建的cL件。但是没有经q预验证的类文g是不能被应用E序理器蝲入的?br /><br />  3、运?MIDlet<br /><br />  我们现在准备在移动设备模拟器中运?MIDletQ如果你现在q处在命令行方式Q请输入 <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>midp firstMIDlet</td></tr></tbody></table><br />  应该可以看到下面的输出结果:(x)<br /><br /><br /><span id="msyq2em" class="f14"><br />  <b>W二?装MIDlet</b><br /><br />  下面我想谈谈装MIDlet的相关知识,即介l一?MIDlet套g以及(qing)Java档案和应用程序描q器文gQؓ(f)?jin)说明方便,我们q将写一个MIDletE序q利用上面介l的那个MIDletE序Qƈ创徏JAR文g和JAD文g来封装这些程序。我们还要看着如何使用 JavaE序包改变我们的开发过E。最后你学?fn)如何从一个Web服务器上讉K MIDlet?br /><br />  <b>MIDlet套g</b><br /><br />  虽然把MIDlet装q?Java档案文g(JAR)q不一定必要,但这是发?J2ME/MIDP应用E序最常见的方法。MIDlet套g是一个MIDlet中所有的文g以及(qing)作ؓ(f) MIDlet一部分的必需的资源的集合。MIDlet套g׃下几部分l成Q?br /><br />  1、附在JAR文g中的 JavacLӞ <br /><br />  2、描q?JAR文g内容的清单文?<br /><br />  3、附?JAR文g中的资源(如图?和Java应用E序描述W文?JAD) <br /><br />  4、应用程序管理器<br /><br />  应用E序理器是一个移动设备上的Y件程序,q个应用E序与具体的讑֤有关Qƈ且由讑֤的生产商实现。它负责安装、运行以?qing)从讑֤上删?MIDletQ而提供错误处理支持。这个应用程序管理器同时q提供一个可选界面,允许用户启动、终止以?qing)删?MIDlet?br /><br />  <b>Java档案文g</b><br /><br />  一个商品化的、封装过应用E序通常p多文件构成。除?JavacM外,其他文g诸如囑փ和应用程序数据即通常所说的资源Q也可能是这个程序包的一部分。你把所有这些信息捆l进一个整体,q?JAR文g?br /><br />  除了(jin)cd资源文gQ一?JAR文gq包括描q?JAR内容的清单文件。清单文件名?manifest.mfQ储存在 JAR文g本n中,下面q张表中列出定义在这个清单文件中的所有可用的属性? <table cellspacing="0" width="585" align="center" border="1"><tbody><tr><td colspan="2"><b>?1</b></td></tr><tr><td width="215"><div align="center">属?/div></td><td valign="center" width="360"><div align="center">用?/div></td></tr><tr><td width="215">MIDlet-Name</td><td width="360">MIDletE序包的名称。例如“Game Pack?/td></tr><tr><td width="215">MIDlet-Version</td><td width="360">MIDlet的版本号</td></tr><tr><td width="215">MIDlet-Vendor</td><td width="360">MIDlet的创或提供?/td></tr><tr><td width="215">MIDlet-Icon</td><td width="360">应用E序理器把q个图标?MIDlet-Name相关联,q是一个图形文Ӟ?PNG图象格式储存?/td></tr><tr><td width="215">MIDlet-Description</td><td width="360">描述 MIDlet的文?/td></tr><tr><td width="215">MIDlet-Info-URL</td><td width="360">可能提供更多MIDlet?或供应商信息?URL</td></tr><tr><td width="215">MIDlet-<n></n></td><td width="360">q个属性包括三D信息:(x) ??MIDlet名称 ??用于q个 MIDlet的图?可? ??应用E序理器将调用来加载这?MIDlet的类?在我们的?Game Pack”例子中Q有两个条目Q?MIDlet-1: KOF, /images/kof.png, kof.kofMIDlet MIDlet-2: Golf, /images/golf.png, golfMIDlet</td></tr><tr><td width="215">MIDlet-Jar-URL</td><td width="360">JAR文g?URL</td></tr><tr><td width="215">MIDlet-Jar-Size</td><td width="360">JAR文g的大?/td></tr><tr><td width="215">MIDlet-Data-Size</td><td width="360">持久数据存储必需的最字节数</td></tr><tr><td width="215">MicroEdition-Profile</td><td width="360">MIDlet需要哪一U?J2ME?/td></tr><tr><td width="215">MicroEdition-Configuration</td><td width="360">MIDlet需要哪一U?J2ME配置</td></tr></tbody></table>  q些属性ƈ不是全部都需要,可是Q没有下面列出的q六个,应用E序理器就?x)拒l加载这?JAR?br /><br />   MIDlet-Name <br /><br />   MIDlet-Version <br /><br />   MIDlet-Vendor <br /><br />   MIDlet-<n></n><br /><br />   MicroEdition-Profile <br /><br />   MicroEdition-Configuration <br /><br />  q里有一个简单的清单文g的例子:(x)<br /><br />   MIDlet-Name: KOF2001<br /><br />   MIDlet-Version: 1.0<br /><br />   MIDlet-Vendor: NeoRage Corporation Inc.<br /><br />   MIDlet-1: kof, /images/kof.png, kof.kofMIDlet<br /><br />   MicroEdition-Profile: MIDP-1.0<br /><br />   MicroEdition-Configuration: CLDC-1.0<br /><br />  <b>Java应用E序描述器文ӞJADQ?/b><br /><br />  虽然没有必要Q你仍然可以?JAR文g中包含一?JAD文g,像清单文g一Pq个文g也包?MIDlet的信息。创Z?JAD文g是基于两个原因?br /><br />  1、向应用E序理器提供信息,说明 JAR文g的内容,使用q些信息Q就可以判断一?MIDlet是否适合q行在这个设备上。例如,通过查看属?MIDlet-Data-SizeQ应用程序管理器可以定 MIDlet是否需要比讑֤可以提供的更多的内存?<br /><br />  2、提供一U方法,可以把参C送到 MIDlet而不必更?JAR文g,在本文的后半D|们将看一个这L(fng)例子?<br /><br />  JAD文g使用?1中相同的属性。如果你需要创Z自己的属性,也可以办得到Q只要用不?MIDlet为开头的属性名可以了(jin)Q下面的 showProperties.jad文g是自定义属性的例子。和清单文g一P有某些属性必被定义Q如果这些属性不可用的话Q应用程序管理器不加蝲q个 MIDletQ它们是Q?br /><br />   MIDlet-Name <br /><br />   MIDlet-Version <br /><br />   MIDlet-Vendor <br /><br />   MIDlet-<n></n><br /><br />   MIDlet-Jar-URL <br /><br />   MIDlet-Jar-Size <br /><br />  MIDlet-Name、MIDlet-Version和MIDlet-Vendor的值必M JAR中的清单文g中相同的属性的g致。可能看出,如果在这两个文g有什么不同的话,甌理器不也会(x)加蝲q个 JAR?br /><br />  除了(jin)q些属性以外,如果两个文g中的另外名称相同的属性,但是属性g相同的,优先采取应用程序描q器文g ( JAD )属性?br /><br />  MIDP 1.0规范没有规定 MIDlet-n属性是 JAD文g的必需属性。可是,没有q个属性,没有办法在讑֤模拟器中预览 MIDlet。在两个文g中包含这个属性没有问题,q且事实上,那么做可以更清楚看出q些文g是怎样兌的。因此,Z完整性考虑Q这里的所有离子都在JAD文g中包含MIDlet-n属性。因此,Z完整性考虑Q这里的全部例子都将?JAD文g中包?MIDlet-n属性?br /><br />  下面是一个非常简单的例子Q?br /><br />   MIDlet-Name: Note Pad<br /><br />   MIDlet-Version: 1.0<br /><br />   MIDlet-Vendor: ABC WorkGroup.<br /><br />   MIDlet-Jar-URL: http://www.abcworkgroup.com/MIDlets/notepad.jar<br /><br />   MIDlet-Jar-Size: 26248<br /><br />   MIDlet-1: NotePad, /images/NotePad.png, NotePad.Main<br /><br />  <b>从MIDlet中访?JAR/JAD属?/b><br /><br />  一个MIDletE序可以讉K所有的定义在清单文?在JAR文g中)(j)和JAD文g的属性。返回属性信息的Ҏ(gu)?qing)所在的完整的程序包名是javax.microedition.midlet.MIDlet.getAppProperty(String name)<br /><br />  下面是一个例子,从jar/jad文g中读出ƈ打印属性倹{?br /><br />  showProperties.jar中的 manifest.mf文g的内容如下:(x) <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet-Name: Show Properties MIDlet<br />MIDlet-Version: 1.0.1<br />MIDlet-Vendor: ABC WorkGroup.<br />MIDlet-1: ShowProps, , showProperties<br />MicroEdition-Profile: MIDP-1.0<br />MicroEdition-Configuration: CLDC-1.0<br />MIDlet-Description: A simple property list example<br />MIDlet-Data-Size: 1500</td></tr></tbody></table><br />  showProperties.jad的内容:(x) <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet-Name: Show Properties MIDlet<br />MIDlet-Version: 1.0.1<br />MIDlet-Vendor: ABC WorkGroup.<br />MIDlet-Jar-URL: file://showProperties.jar<br />MIDlet-Jar-Size: 1132<br />MIDlet-1: ShowProps, , showProperties<br />JadFile-Version: 1.5<br />MIDlet-Data-Size: 500</td></tr></tbody></table><br />  showProperties.java的源E序: <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>import javax.microedition.midlet.*;<br />public class showProperties extends MIDlet<br />{<br />public void startApp() throws MIDletStateChangeException<br />{<br />System.out.println("Vendor: " + getAppProperty("MIDlet-Vendor"));<br />System.out.println("Description: " + getAppProperty("MIDlet-Description"));<br />System.out.println("JadFile Version: " + getAppProperty("JadFile-Version"));<br />System.out.println("MIDlet-Data-Size: " + getAppProperty("MIDlet-Data-Size"));<br />}<br />public void pauseApp()<br />{ }<br />public void destroyApp(boolean unconditional)<br />{ }<br />}</td></tr></tbody></table><br />  下面q些是一些比较重要的地方Q?br /><br />  manifest.mf文g作ؓ(f) JAR文g showProperties.jar的一部分储存的?<br /><br />  JAD文gshowProperties.jad使用MIDlet-Jar-URL: file://showProperties.jar 引用showProperties.jar?<br /><br />  当你览q个 JAD文g的时候,它用上面那个命令找出相兌?JAR文gq读取清单文件的内容?<br /><br />  属性MIDlet-Name、MIDlet-Version和MIDlet-Vendor 既在 JAR中的清单文g中又?JAD文g中,q些属性的值都必须完全相同?<br /><br />  MIDlet-Description属性来自清单文Ӟ是可选的?<br /><br />  JadFile Version属性不在表 1中,因此它是一个自定义属性。因?JAD文g内的属性可从MIDlet讉KQ所以你可以不用改变 JAR文g而添加属性到 JAD中?<br /><br />  属?MIDlet-Data-Size在清单文件和 JAD文g中都有,像前面指出的那P当两个文件中有完全相同的属性时Q?JAD文g中的属性将使用。切记这不适用于MIDlet-Name、MIDlet-Version和MIDlet-Vendor?<br /></span><br /><font style="BACKGROUND-COLOR: #f6fafb">  </font><b>?MIDlet套g中封装多?MIDlet</b><br /><br /><font style="BACKGROUND-COLOR: #f6fafb">  在我们谈论如何封装多?MIDlet之前Q我们先得多写几个可用的MIDlet。下面有两个单的 MIDlet。第一个显CZ个带有简短消息的文本框组件?br /><br />  MIDlet1.java源程序:(x) </font><table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>import javax.microedition.midlet.*; <br />import javax.microedition.lcdui.*; <br />public class MIDlet1 extends MIDlet implements CommandListener<br />{<br /> private Display display; // 引用Display对象 <br /> private TextBox tbxMain; // 昄消息的文本框 <br /> private Command cmdExit; // 退出MIDlet的命?<br /> // 构造程?<br /> public MIDlet1() <br /> { <br />  display = Display.getDisplay(this); <br />  cmdExit = new Command("Exit", Command.SCREEN, 1); <br />  tbxMain = new TextBox("MIDlet 1", "Welcome", 50, 0); <br />  tbxMain.addCommand(cmdExit); <br />  tbxMain.setCommandListener(this); <br /> } <br /> // 启动MIDlet时由应用E序理器调?<br /> public void startApp()<br /> {<br />  display.setCurrent(tbxMain);<br /> }<br /> // 一个必要的Ҏ(gu) <br /> public void pauseApp()<br /> { }<br /> // 一个必要的Ҏ(gu) <br /> public void destroyApp(boolean unconditional)<br /> { }<br /> file://(g)查一下是否选择Exit命o(h) <br /> public void commandAction(Command c, Displayable s)<br /> {<br />  if (c == cmdExit)<br />  {<br />   destroyApp(false);<br />   notifyDestroyed();<br />  }<br /> }<br />}</td></tr></tbody></table><br />  W二个MIDlet使用Listlg昄消息(MIDlet2.java): <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>import javax.microedition.midlet.*;<br />import javax.microedition.lcdui.*;<br />public class MIDlet2 extends MIDlet implements CommandListener<br />{<br /> private Display display; file://引用Display对象 <br /> private List lstMain;<br /> private Command cmdExit; // 退?MIDlet的命?<br /> // 构造程?<br /> public MIDlet2()<br /> {<br />  display = Display.getDisplay(this);<br />  cmdExit = new Command("Exit", Command.SCREEN, 1);<br />  lstMain = new List("MIDlet 2", Choice.IMPLICIT);<br />  lstMain.append("Welcome Back", null);<br />  lstMain.addCommand(cmdExit);<br />  lstMain.setCommandListener(this);<br /> }<br /> file://启动MIDlet时由应用E序理器调?<br /> public void startApp()<br /> {<br />  display.setCurrent(lstMain);<br /> }<br /> file://一个必要的Ҏ(gu) <br /> public void pauseApp()<br /> { }<br /> file://一个必要的Ҏ(gu) <br /> public void destroyApp(boolean unconditional)<br /> { }<br /> file://(g)查一下是否选择Exit命o(h) <br /> public void commandAction(Command c, Displayable s)<br /> {<br />  if (c == cmdExit)<br />  {<br />   destroyApp(false);<br />   notifyDestroyed();<br />  }<br /> }<br />}</td></tr></tbody></table><br /><br />  W一个程序名?MIDlet1.javaQ第二个E序名ؓ(f) MIDlet2.java。在你保存这些文件的目录里,q行下列命o(h)~译q验证q些文g? <table width="548" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>javac -bootclasspath c:mefcs*.java <br />preverify -classpath c:mefcs;. -d . MIDlet1 MIDlet2 <br />jar cvfm MIDlets.jar manifest.txt MIDlet1.class MIDlet2.class spin.png</td></tr></tbody></table><br />  <b>创徏 JAR文g</b><br /><br />  创徏一个新文gQ取名ؓ(f) manifest.txtQ然后输入如下内容:(x) <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet-Name: MIDlet Examples<br />MIDlet-Version: 1.0<br />MIDlet-Vendor: My Corporation Inc.<br />MIDlet-1: MIDlet1, /spin.png, MIDlet1<br />MIDlet-2: MIDlet2, /spin.png, MIDlet2<br />MicroEdition-Profile: MIDP-1.0<br />MicroEdition-Configuration: CLDC-1.0</td></tr></tbody></table><br />  q行下列命o(h)创徏一?JAR文gQ? <table width="566" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>jar cvfm MIDlets.jar manifest.txt MIDlet1.class MIDlet2.class spin.png</td></tr></tbody></table><br />  q将创徏一个名?MIDlets.jar?JAR文gQ包?manifest.txt文g和上面两个类文g?br /><br />  <font color="#ff0000"><b>注意Q?/b></font> JAR中的清单文g名应?manifest.mf?br /><br />  <b>创徏 JAD文g</b><br /><br />  创徏一个新文gQ取?MIDlets.jadQ? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet-Name: MIDlet Examples <br />MIDlet-Version: 1.0 <br />MIDlet-Vendor: My Corporation Inc. <br />MIDlet-Description: Two simple examples to show how to compile and run a MIDlet <br />MIDlet-Jar-URL: http://localhost/MIDlets.jar <br />MIDlet-Jar-Size: 2604 <br />MIDlet-1: MIDlet1, /spin.png, MIDlet1 <br />MIDlet-2: MIDlet2, /spin.png, MIDlet2</td></tr></tbody></table><br />  注意q两?MIDlet的引用:(x) <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet-1: MIDlet1, /spin.png, MIDlet1<br /><br />MIDlet-2: MIDlet2, /spin.png, MIDlet2</td></tr></tbody></table><br />  上面每一行都包括在设备上昄?MIDlet?( MIDlet1?MIDlet2 )Q在每个MIDlet名旁边,应用E序理器都?x)显CZ个图象文Ӟ以及(qing)启动 MIDlet的类文g?br /><br />  <b>q行 MIDlet</b><br /><br />  你既可以从一个局域网文gpȝ也可以从一?Web服务器中q行MIDlet,现在我将分别介绍一下?br /><br />  从文件系l运?br /><br />  键入下列命o(h)来预览MIDletQ? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>midp -transient file://MIDlets.jad</td></tr></tbody></table><br />  -transient选项告诉模拟器,你想q行一个指?url中可扑ֈ的描q文件。在本例中,file://MIDlets.jadQ这当前目录查找 MIDlets.jad。如果有必要的话Q你q可以给Z?JAD文g的完整的路径。比如说Q我?JAD文g的完整\径是 <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>file://J2ME/MIDlets/welcome.jad</td></tr></tbody></table><br />  下面的图片显CZ(jin)应用E序理器的ȝ面和 MIDlet1?MIDlet2的输出? <table width="500" align="center" border="0"><tbody><tr><td><a target="_blank"><img alt="" src="http://images.csdn.net/20050808/0eef8070-a91f-430a-b538-445e36b5c8d9.gif" border="0" /></a></td></tr></tbody></table><br />  ?Web服务器上q行<br /><br />  你还可以从一?Web服务器上q行 MIDletQ在上蝲 JAR?JAD文g之后Q通过改变 url讉K JAD文gQ? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>midp -transient http://localhost/MIDlets.jad</td></tr></tbody></table><br />  q将讉Kq行在我的电(sh)脑上的Web服务器上?MIDlets.jad文gQ如果你把文件上传到互联|上?Web服务器,只需直改变适当域名Q? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>midp -transient http://www.yourwebserver.com/path/MIDlets.jad</td></tr></tbody></table><br />  使用 JavaE序包的目理<br /><br />  按照下列步骤创徏最后一个MIDletQ?br /><br />  1. 创徏用于新项目的目录Q我使用的名UCؓ(f) MIDletPackageQ是c:me的子目录?br /><br />  2. 在新建目录内Q创Z个新的子目录Q?jclasses?pclasses?resources<br /><br />  有了(jin)q些附加的目录,能够很容易找到特定的文g。例如,所有的图象文g和其他资源都攑օ /resources子目录;所有的?Java~译E序创徏的类文g都置?/jclasses子目录;l过预验证的cȝ?pclasses子目录中。下面是我的pȝ中的目录l构Q? <table width="500" align="center" border="0"><tbody><tr><td>c:j2me <br />| <br />MIDletPackage => Java 源代码和manifest.txt文g <br />| <br />jclasses => 从Java~译器编译的c?<br />pclasses =>l过预验证的c?<br />resources =>资源文g (囑փ文g{?<br /></td></tr></tbody></table><br />  3. 更新文gQ复?Java源文? MIDLet1.java?MIDlet2.java)?MIDletPackage目录Qƈ在每个文件头部添?package语句Q如下:(x)而且Q如果你已经使用一个图象文件的话,把这个文件复制进 resources目录中? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>MIDlet1.java: <br />package simpleMIDlets; <br />import javax.microedition.midlet.*; <br />import javax.microedition.lcdui.*; <br />public class MIDlet1 extends MIDlet implements CommandListener <br />{<br /><br />...<br /><br />}<br /><br />MIDlet2.java: <br /><br />package simpleMIDlets; <br />import javax.microedition.midlet.*; <br />import javax.microedition.lcdui.*; <br />public class MIDlet2 extends MIDlet implements CommandListener <br /><br />{<br /><br />...<br /><br />}</td></tr></tbody></table><br />  4、参考图象文件和cL件的新的位置更新 manifest.txt?JAD文g? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>manifest.txt: <br />MIDlet-Name: MIDlet Examples <br />MIDlet-Version: 1.0 <br />MIDlet-Vendor: My Corporation Inc. <br />MIDlet-1: MIDlet1, /resources/spin.png, simpleMIDlets.MIDlet1 <br />MIDlet-2: MIDlet2, /resources/spin.png, simpleMIDlets.MIDlet2 <br />MicroEdition-Configuration: CLDC-1.0 <br />MicroEdition-Profile: MIDP-1.0 <br /><br /><br />MIDlets.jad: <br />MIDlet-Name: MIDlet Examples <br />MIDlet-Version: 1.0 <br />MIDlet-Vendor: My Corporation Inc. <br />MIDlet-Description: Packaging multiple MIDlets <br />MIDlet-Jar-URL: http://localhost/MIDlets.jar <br />MIDlet-Jar-Size: 2884 <br />MIDlet-1: MIDlet1, /resources/spin.png, simpleMIDlets.MIDlet1 <br />MIDlet-2: MIDlet2, /resources/spin.png, simpleMIDlets.MIDlet2</td></tr></tbody></table><br />  注意MIDlet-1和MIDlet-2的更改,被引用的cL件?simpleMIDlets.MIDlet1?simpleMIDlets.MIDlet2包名?br /><br />  5、编译:(x)~译源程序:(x) <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>javac -bootclasspath c:mefcs-d jclasses *.java</td></tr></tbody></table><br />  -d选项告诉~译E序Q把cL件写?jclasses目录?br /><br />  6、预验证Q? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>preverify -classpath c:mefcs; -d pclasses jclasses</td></tr></tbody></table><br />  -d选项告诉预验证器把经q预验证的类保存?pclasses目录下。最后的 jclasses告诉预验证器C么地方寻N些要预验证的cR?br /><br />  7、创?JARQ运?jarE序Q? <table width="500" align="center" border="0"><tbody><tr bgcolor="#ebe9eb"><td>jar cvfm MIDlets.jar manifest.txt -C pclasses . resources </td></tr></tbody></table><br />  创徏一个名?MIDlets.jar的文Ӟ使用文g manifest.txt作ؓ(f)清单文g的内?(一个名?manifest.mf的文件将被保存在 JAR??<br /><br />  q行MIDletQ有两种情况Q?<br /><br />  Q?Q从文gpȝ中运行MIDletQ? <table width="500" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>midp -transient file://MIDlets.jad</td></tr></tbody></table><br />  Q?Q从web服务器上q行MIDletQ把JAR文g和JAD文g上传到web服务器,输入下面的命令来览MIDletQ? <table width="500" align="center" border="0"><tbody><tr bgcolor="#ebe9eb"><td>midp -transient http://localhost/MIDlets.jad</td></tr></tbody></table></dd> <img src ="http://www.tkk7.com/zjw-albert/aggbug/57136.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjw-albert/" target="_blank">zjw_albert</a> 2006-07-07 14:59 <a href="http://www.tkk7.com/zjw-albert/archive/2006/07/07/57136.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲]J2ME之谜http://www.tkk7.com/zjw-albert/archive/2006/07/07/57135.htmlzjw_albertzjw_albertFri, 07 Jul 2006 06:57:00 GMThttp://www.tkk7.com/zjw-albert/archive/2006/07/07/57135.htmlhttp://www.tkk7.com/zjw-albert/comments/57135.htmlhttp://www.tkk7.com/zjw-albert/archive/2006/07/07/57135.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/57135.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/57135.html
Java嵌入式开发之?

J2ME之谜


  W一?引言 J2ME概述

  到目前ؓ(f)止,大部分h都已非常熟?zhn)?Java 2q_Q以?Sun如何?Java技术分成三个版?(标准版、袖珍版以及(qing)企业版)(j)QSun ?999q?月时推出?Java 2袖珍?(J2ME)来满x(chng)费电(sh)子和嵌入讑֤的需要。J2ME是ؓ(f)?jin)那些用有限的能源、有限的|络q接 (常常是无U连?以及(qing)有限囑Ş用户界面能力的设备开发的。它最初的目标?16位或 32位处理器Q?6 MHz旉频率Q?512K或更内存的讑֤。乍一看之下, J2ME像一个没有绑定明显主题的松散的应用程序接口和技术规范。我们想通过说它不是什么东西的Ҏ(gu)来描q它Q它不是一l用于台式机 Java应用E序规范Q如果你再观察仔l一些,你会(x)发现所有的 J2MElg都围l一个中?j),q些中心(j)被称为configuration(配置 QSun的市(jng)销资料也称它们 design centersQ设计中?j)?j)Q它们中间的每一个都是用于消费电(sh)子和嵌入讑֤的特别的cR?

  Connected limited device configuration(有限q接讑֤配置Q简U?CLDC ) q个配置定义?Java应用E序接口以及(qing)支持手持讑֤的技术,像 Sun的文档中所描述的那P " devices that you hold in your handQ你握在手中的设备)(j) " Palm序列手持讑֤可能是这一领域的设备的最好的例子Q特别是它有开?CLDC的功能以?Palm讑֤q行期系l可用?
Connected device configuration(q接讑֤配置 CDC ) q个配置定义支持?Sun文档中所_(d) " devices that you plug into plug into the wallQ你插入墙的讑֤Q的讑֤的应用程序接口和技术,q样的设备的一个例子可能就是机盒?

  q两U配|不同的地方在于它们应用于的装|的能力Q?CLDC讑֤的处理器能力有限 (与台式机pȝ比较 )Qƈ且存储器大小一般也只在128 KB?512 KB之间Q?与此同时Q?CDCpȝ׃同了(jin)Q它可能?32位或 64位处理器Q以?qing)有限的存储定wQ不q它的下限也得超q?12K?它遵循的原则是Q每个不同的能力g的配|都被不同的虚拟机支持?Z CDC的系l用一个功能强劲的虚拟机,而基?CLDCpȝ的?KVM (我过?x)儿会(x)介l)(j)?br />
  每个配置代表一U低水^的,基本的应用程序接口,在这两个怼基础之上?profileQ简表)(j)Q用于特D设备的额外的应用程序接口?我想通过看一张来自SUN提供的文档中的图?(参见?1 )来解释这其中的关pR?



图一解释 配置和简表的体系l构 J2ME的体pȝ构被横向地分成三层,U向分成两部分。配|包括一个控刉|核?j)类的虚拟机Q?具体?表位于每个配|之上?/font>


  J2ME现在定义两个配置Q?Connected Device configuration(q接讑֤配置 CDC )和限制性更强的 Connected Limited Device Configuration (有限q接讑֤配置)?/font> 表的实现?Java应用E序接口的一个集合,用于适应被定义配|的应用E序接口提供的服务,表是一个完整的q行环境Q一个在表上执行的应用程序不需要额外的支持cR?

  J2ME没有定义满q两U配|的标准化用h口,Sun也承认现在的消费讑֤多种多样Q用L(fng)面也各不一P所以定义一个可用于所有用L(fng)界面是一场失败的战(sh)?J2ME中的用户界面定义在简表中?/p>

  W二?J2ME的体pȝ?/b>

  现在个h计算机系l的数量和种cdl发展到无法控制的地步,请你想一惻I你编写的E序q行在“信息家?sh)”舞台的情景吧,q些信息家电(sh)包括呼叫器,行动?sh)话Q像Palmq样的个人数字助?PDA)Q电(sh)视机盒QPOSl端以及(qing)其他的消费电(sh)子设备。现在全世界上光是手提电(sh)话生产商有许多Q更不用说别的家?sh)设备?jin)Q而且每一U家?sh)设备又有不同的?gu)和界面。所以,你可以想刎ͼ Java应用E序的轻便性以?qing)能够解军_发这么许多不同的讑֤E序的能力,使大家对J2ME有很大的期许。当?dng)Z(jin)更好的开发这些信息家?sh),p求把Java的精髓压~进一个非常小的程序包中,q就是J2ME?

  J2ME是一U通过许多部g和规范的技术, q众多的部g和规范帮?J2ME来满众多的消费品的不同的需要。和所有的爪哇E式语言技术一P在它的核?j)属于一U虚拟机?像使用所?Java技术一PJ2ME的核?j)也在一U虚拟机中?最初,用于 J2ME应用E序虚拟机的被称?Kilobyte virtual machine或简U?KVM。就像它名称的含义, KVM比较?yu),通常只有 128K或更。这比v我们通常?jin)解和用?Java 2标准?Java虚拟?( JVM )?32 MB来说小得多?jin)?

  用于q接虚拟机的是一pd配置和简表,它们提供?jin)用于特?J2ME环境的类应用E序接口(见图二)(j)?每个配置和简表处理一般或具体的消费品,配置和简表规范是由多U多L(fng)讑֤生商和用户共同开发ƈ建立的。配|是用于一l通用讑֤的最的 Javaq_Q?常常归ؓ(f)一U横向的讑֤分组Q相Ҏ(gu)_(d)横向分组讑֤是那些共享相同的内存安排Q通信带宽Q能量需求以?qing)用戯力的讑֤Q一般认为配|能够提供这众多的设备的所有需求?
图二解释Q?J2ME层次 Java虚拟机是 J2ME技术的核心(j)Q但是配|和表提供特D环境的cd用程序接口。配|是用于一l通用讑֤的最的 Javaq_Q而简表则为具体的讑֤家族或特别的应用E序提供更具体的能力?/font>

  J2ME领域的新的开发者常常被q些事实困惑的, 事实上, Sun的第一个配|?现在只是一U配|的引用实现 )带有UCؓ(f) KVM的虚拟机引用实现Q?KVM满配置的虚拟机的必要条件。然而, Sun?KVM也可以被另外一个虚拟机所代替Q现在, 正是因ؓ(f)配置和虚拟机l合得有点紧密,因此D?jin)这么多的؜乱?

  另一斚wQ简表完善了(jin) 配置Qؓ(f)某个具体的设备家族或某个具体的工业片D应用程序提供更高的性能?换言之, 表ؓ(f)具体的纵向市(jng)场的讑֤比如说行动电(sh)话提供更多的性能。这里的关键是 表必d?配置Q?没有 配置和虚拟机提供核心(j)cd用程序接口和q行期环境的话,表也不会(x)工作?br />
  通常Q简表ؓ(f)一U给定的垂直分组讑֤提供用户界面、输入法、持久性机制。这c?表被认ؓ(f)是发展这些设备应用程序的完整的工具包。我们见到最多的应用E序表的例子q动电(sh)话简表和个h数字助手(PDA)?其他表ؓ(f)范围宽广的设备提供非常特D的功能或应用程序可UL性,q方面的例子是提供q程Ҏ(gu)调用 ( RMI )功能的简表和提供l一银行事务的简表?br />
  虚拟机?配置?表…你是不是已l被搞迷p了(jin)Q?如果q样的话Q我们就来简化一?J2ME体系l构吧?如果你想为小型信息家늼?Java应用E序的话Q你需要两个前提:(x)一?配置和至一?表?现在Q?一般是配置捆绑?jin)虚拟机和一套针对你的^台所能够用的横向分组讑֤的Javacd。其ơ,你至还需要一?表来Z的^台提供附加的 Javac,q个 表通常?x)?f)你的讑֤提供用户界面、输入和数据库类。有?jin)这两个前提Q你׃(jin)使用 JavaZ的设备编写应用程序的基本的J2ME环境?


  W三?详细谈谈J2ME配置

  J2ME可以在好几个不同的配|中q行配置?像先前提到的,每个配置Zl通用讑֤提供最的 Javaq_Q到目前为止Q只有两U配|规范。通过 Java规范定义的这两种配置?Connected Limited Device Configuration (有限q接讑֤配置Q?CLDC )?Connected Device Configuration (q接讑֤配置 CDC )?br />
  CLDC是ؓ(f)使用较小的存储容量的讑֤设计?(参见? )?CLDC用于内存?28?512K之间的消费电(sh)子设备, q一cd中典型代表的讑֤包含呼叫器、行动电(sh)话、PDA和POSl端Q而另一斚wQ?CDC用于?PC机小但是h?512K内存多的讑֤Q这一c设备包括互联网l电(sh)视系l、机盒、POSpȝ、汽车导航以?qing)娱乐系l。一般来_(d) CDC使小型设备只要具有少量的资源Q至比台式的资源pq行Java~程Q而CLDC使小型设备所拥有的资源只要比一张智能卡多一点就可以q行Java~程?jin)?
图二解释 讑֤覆盖的范?J2ME有两个配|CLDC?CDCQCLDC是ؓ(f)使用较小的存储容量的讑֤设计的,而CDC用于?PC机小但是h?512K内存多的讑֤?/font>

  除了(jin)在容量大和能力上对虚拟定了(jin)必要条gQ配|还规定?jin)类应用E序接口要包含常见的 java.io?java.net?java.util?java.lang包,配置可能q要包括其他需要的E序包?

  CLDC

  CLDCh可以q溯?999qJavaOne大会(x)上介l的Sun的第一个袖珍版 Java和第一?KVM以及(qing)相关的类库,虽然 CLDC和所有的配置都满x(chng)拟机的条Ӟ可它本nq(sh)是虚拟机QCLDC的引用实现只是包含在当前的分布中?KVM?br />
  Ҏ(gu)规范中所_(d)q行 CLDC的设备应该有 512K或更的内存I间、一个有限的甉|供给 (通常是用电(sh)池)(j)、有限的或断断箋(hu)l的|络q接?( 9600 bps或更?)以及(qing)多样化的用户界面甚至没有用户界面?通常说来Q这个配|是Z人化的、移动的、有限连接信息设备而设计,比如呼叫器、移动电(sh)话和 PDA{?br />
  ?J2SE相比Q?CLDC~少下列所说的q些特征Q?br />
  AWTQ抽象窗口开发包Q, Swing或其他图形库

  用户定义c装载器

  cd例的最l化

  q引用

  RMI

  ReflectionQ映)(j)

  CLDC有四个包Q?java.lang?java.util?java.io?javax.microedition?除了(jin) microedition包以外,其他的这几个包都是J2SE包的核心(j)子集QCLDC采用q些J2SEcdQ但是把其中一些在微型讑֤中用不到cR属性、方法去掉了(jin)。因?CLDCcd有许多细微的差别?如果(zhn)想研究J2SE?CLDCcd之间的差别,请参阅相x(chng)档,在此׃详细说明?jin)?br />
  惌理解Z么CLDC去除q么多J2SE中重要的cd特征Q请回想一下与 CLDC相关的两条基本原理。首先,它只?512K的内存空_(d) 而像RMI和映需要的内存太大?jin)?其次Q配|必Lؓ(f)一l通用讑֤提供最的 Javaq_?在个人移动信息设备领域中Q许多系l都不能支持 J2SE中的众多的高U特征?例如Q许多消费电(sh)子品不能支持QҎ(gu)Q?因此 FloatQQ点类Q和 DoubleQ双_ֺc)(j)p删除?jin)?再看另外一个例子,许多pȝ没有或不提供讉K一个文件系l的功能或权限?因此与文件有关的cM被丢弃了(jin)。又如,错误处理是一个代价非帔R的过E处理,在许多消费电(sh)子设备中Q故障恢复是很难的甚x(chng)不可能的?所以在 CLDC中,许多错误处理cM被删除了(jin)?

  java.microeditionE序包提供了(jin)一个一般的l构来替代许?J2SE|络输入/输出cR?CLDC一般连接器l构q定义了(jin)一?Connectorc,允许许多不同cd的连接能够用静(rn)态方法,下表列出使用同一个Connectorcd建和打开五种不同cd的连接的Ҏ(gu)Q?br />
  HTTP Connector.open("http://www.xyz.com");

  套接?Connector.open("socket://111.222.111.222:9000");

  通讯端口 Connector.open("comm:1;baudrate=9600");

  数据?Connector.open("datagram://111.222.111.222");

  文g Connector.open("file:/xyz.dat");

  一般连接器l构提供l应用程序开发者一个到通用低水q硬件的单的映射表。成功执?open语句返回一个实C般连接界面的对象?

  CDC

  CDC늛?jin)个人?sh)脑与有至?512K内存的小型设备之间的中间地带。现在,q一c设备通常是共享的、固定的 (不用Ud)|络q接信息讑֤Q像?sh)视机机盒Q网l电(sh)视系l、互联网?sh)话与汽车导?׃pȝ{等?br />
  首先QCDCZ J2SE 1.3应用E序接口Q包含所有定义在CLDC规范(包括 javax.microeditionE序?中的Java语言应用E序接口。与CLDC相比Q?CLDC所有缺的Ҏ(gu)和cd CDC中都被补齐,包含映射、最l化、所有的错误处理cRQҎ(gu)、属性、输?输出 ( File?FileInputStream{等 )和弱的引用?一般说来, CDC中预期的cd括一个J2SE子集和一个完整的 CLDC集Q如?中所C:(x)

? QJ2SE、CLDC和CDC的关p?
  像使用所有的配置一PCDC有基层虚拟机的具体的必要条g?Ҏ(gu) CDC规范Q基层虚拟机必须提供实现完整?Java虚拟机的支持 ?如果虚拟机实现有一个用于激z设备的本地Ҏ(gu)的界面,它必d?JNI 1.1版本?如果虚拟机实现有一个调试界面,它必d?Java虚拟试界?( JVMDI )规范?如果虚拟机有一个简表界面,它必d?Java虚拟机简表界?( JVMPI )规范?可见Qؓ(f)?jin)实现这些功能,CDC肯定?x)变得很大,׃能称其?f)K虚拟Z(jin)Q因此,我们通常U用于CDC的虚拟机?CVMQ这里的 C代表 compact、connected、consumer?br />
  W四?谈谈J2ME?/b>

  虽然配置Zl通用讑֤提供?jin)最的 Javaq_Q但是应用程序开发者感兴趣的是Z个个别的讑֤生应用E序Q当他们只是使用配置的话Q他们编写的应用E序׃(x)有一些欠~?配置必须满所有的讑֤的最的要求Q?用户界面、输入机制和数据持久性有高度地设备具体性,每一U设备都有自q用户界面、输入机制和数据存储Ҏ(gu)Q这些往往不在配置所满的最要求的范围之内?

  表ؓ(f)相同消费?sh)子讑֤的不同的生商提供?jin)标准化的 JavacdQ?事实上,虽然配置规范的开发由 Sun领导Q但是许多简表规范仍l由Ҏ(gu)讑֤的供应商领导?比如_(d) Motorola领导?jin)行动?sh)话和呼叫器简表规范的开发,又如 Palm 领导 PDA表的开发?

  现在Q五个已知简表已l有?jin)规? CQ每个简表的责Q都是Z(jin)完善配置的不I下表列出?jin)这五个表:(x)

?/td>完善配置
Mobile information devices profile (MIDP)Ud?sh)话和呼叫?CLDC
Personal digital assistant profilePalm和Handspring的PDA 讑֤ CLDC
Foundation profile用于所有不需要GUI的CDC讑֤的标准简?CDC
Personal profile替代PersonalJava的Foundation完善的简?CDC
RMI profile 提供RMI的Foundation完善的简?CDC
 
  现在我想谈一谈另一个Javacd集,它现在差不多可以被认为是另一个简表了(jin)。当Sun为Palm开发第一个KVMӞ他们需要一l类?开发Palm的演C程序。这套类库被装q?com.sun.kjavaE序包, ?CLDC早期的开发中Q这些类被广泛的使用来测试和演示 J2ME。因?kjava是唯一的允许应用程序开发者?J2ME?KVM开发应用程序的c,所以它?yu)pq泛使用?jin)。甚臛_?jin)今天,一个用?PDA或更Ҏ(gu)一点的 Palm的简表多已经在开发中Q许多开发者仍然希望?kjavacL开?PDA应用E序。尽?kjavacM被支持,q且仅仅用于设计试E序或演C程序,q且它们被一个即到来的表所替代Q但是开发者们仍然热衷于用它来开发?br />
  MIDP

  Mobile Information Device Profile(Ud信息讑֤?,U?MIDP )Q第一个实现的表,补充?CLDCq且提供应用E序语义和控件、用L(fng)面、持久存储器、网l和用于Ud?sh)话的计时器、双通道呼叫器和其他无线?sh)设备?因ؓ(f) MIDP?CLDC两者都有引用实玎ͼ我们可以使用一个例E来研究一下这个简表?br />
  下面的例子是一个允许用戯入代表想知道的基金报L(fng)代号的例子。应用程序然后通过 HTTP接到一个金融网站,获得基金报h(hun)Q把h储存在一个数据库Q然后把hq回l用戗?
// 到如需要的J2MEc?br />import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;

// 扩展MIDletcL构徏我们的自定义MIDlet
public class FundTracker extends MIDlet implements
CommandListener {

file://昄理者变?br />private Display display = null;
file://MIDlet的表单变?br />private RequestForm reqForm = null;

file://MIDlet构徏?br />public FundTracker () {
display = Display.getDisplay(this);
reqForm = new RequestForm("Fund Tracker");
reqForm.initForm();
reqForm.setCommandListener(this);
}

file://开?MIDlet 应用E序
protected void startApp() {
display.setCurrent(reqForm);
}

file://暂停 Midlet
protected void pauseApp() {
}

file://销毁Midlet
protected void destroyApp(boolean unconditional) {
}

file://通过监听者响应命?br />public void commandAction(Command c, Displayable s) {
if (c == reqForm.getExitCommand()) {
destroyApp(false);
notifyDestroyed();
return;
}
if ((c == reqForm.getGetCommand()) &&
(reqForm.getSymField().getString().length() > 0)) {
getAndDisplayQuote();
} else
{
reqForm.getMsgString().setText("Symbol required");
}
}

file://储存?分开的成对的基金字符串和报h(hun)字符?br />private void storeQuote (String fund, String newQuote) {

file://数据库变?

RecordStore quoteDB = null;

try {
quoteDB = RecordStore.openRecordStore(
"FundQuotes", true);
byte[] data = (fund + "#" + newQuote).getBytes();
int size = data.length;
quoteDB.addRecord(data, 0, size);
quoteDB.closeRecordStore();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or
use Fund Quote database.");
}
}

file://通过QuoteServicecd回提交的代号表示的基金报?br />private void getAndDisplayQuote(){
String fundSymbol = reqForm.getSymField().getString();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
reqForm.getMsgString().setText(theQuote);
}
else
reqForm.getMsgString().setText("No quote" +
'' '' + "Check Symbol");
}
}
}


  MIDP应用E序UCؓ(f) MIDletQ?Z(jin)创徏一?MIDletQ你必须写一个扩展基?MIDletcȝc?(像我们在上面代码段中列出的那样Q?q有点类似常见的 applet?servlet?MIDlets独有的东西是把多?MIDletl成一?MIDlet套g的能力?q就允许 MIDlet在一个单独的 JVM环境中共享资源,比如一个数据库{等?事实上,我们上面l出的例子还包括一?MIDlet ( RetrieveQuoteQ见上段E序Q,用于取回所报h(hun)根{?当MIDlet被请求时Q?MIDlet通过构造程序实例化Q然后调用实例的 startApp()Ҏ(gu)?

  ?FundTracker例子中, MIDlet的用L(fng)面或昄是由 Displaycȝ一个实例管理的?对于每个 MIDletQ只有一个显C管理器实例?所有可以显C的目Q像屏幕或画布(canvasQ,通过q个理器都能够成ؓ(f)可见的。因动电(sh)话和呼叫器能力的多样?又因为用于这些设备的应用E序cd的差异, MIDP规范提供?jin)两U类型的用户界面。一个可UL性稍差、明设备、低水^的应用程序接口,允许囑Ş元素_的控制和攄?q个接口cd是用于应用程序特性比较典型的讑֤特别设计的,比如?sh)子游戏?一个可UL性稍好的、抽象的、高U的 GUI应用E序接口Q提供来用于商业应用E序?

  我们的例E用的是高U的应用E序接口和典型的用户界面lg (文本框,列表{等 )Q是q类界面通用的。比如说Q实际的表单和所有的组件在一个单独的文g中都已定义?像在代码段一中列出的那样Q当 MIDlet创徏Ӟ一个表单的实例?MIDlet兌?在调?MIDlet startApp()Ҏ(gu)的时候,通过 Display对象昄表单?使用一个用于表单的c,允许我们在我们简单的报h(hun)(g)索应用程序中重新使用q个表单 ( RetrieveQuote )。ؓ(f)?jin)清晰性和风格Q我们通过一个单独的cL定义报h(hun)服务?Z(jin)演示一般连接器l构的能力,我们的报h务类通过一?Connector实例取回报h(hun)?



  MIDP要求q_讑֤提供一个机制用来储存简单的数据记录Q通过正常的^CӞ比如重新启动和电(sh)池更新维护系l的完整性?MIDPUC个持久数据库?RecordStore?在我们的CZ中, MIDlet打开q添加一条记录到 " MutualFundQuotes " RecordStore?正如我们的演C程序,能添加到 RecordStore中的唯一一U类型的记录是字节数l?相同?RecordStore是一个资源,它可以通过套g׃n?Ҏ(gu) MIDP规范Q??MIDlet从^C删除后,RecordStore也会(x)被从q_中删除?

  PDA?br />
  Palm公司是开发PDA表规范的领头人, q个表也是完善了(jin) CLDCQ在相当长的一D|间内Q它都将?kjavacȝ序包的替代品?Java规范q个 profile臛_应当提供两个核心(j)功能片段Q?一个用L(fng)面显C工具包Q适合?"有限的尺寸和深度昄 "和一个持久数据存储器机制?昄工具包应该是抽象H口工具包的一个子集, 而持久机制将为应用程序、数据、配|?环境信息提供单的数据存储?br />
  Foundation?br />
  下面三种表不是非常常见, q三U简表的职责都是Z(jin)完善 CDC?Personal?RMI表实际上?Foundation表的扩展?Foundation表的d是担M个基表,便于以后开发出来的提供囑Ş用户接口?|络{功能的表附着在它之上?除了(jin)用于基础表, Foundation表还提供完整|络的支持,不管有没有用图形用h口?br />
  Personal?br />
  在当前的规范需求下Q?Personal表提供下一?PersonalJava环境。这个简表允诺,提供互联|连接性和 Web保真度以?qing)一个能够运?Java applets?GUI?br />
  RMI?br />
  回想一?CDC配置为共享的、固定网l连接信息设备提供最的 Java环境?RMI表将通过提供 Java?Java的RMI来协助提供更好的|络q接性?通过使用 J2SE ( 1.2.x或更高版本的 ) RMIQ这个简表将允许q些|络讑֤与其他系l应用程序交互操?(q个pȝ不必也运?J2ME )?br />
  kjavac?br />
  正如前面提到的那P kjavacL最初提供的一个供试用的c,?Palm讑֤上运行早期的 KVM和配|版本?它们被 PDA表代ѝ?kjavacL展了(jin) CLDCq且提供一个图形用h口?Palm数据库访问,单集合类和一个三角法计算器?br />
  在代码段2中,我?com.sun.kjava重写?MIDP FundTrackerE序Q让它在 Palm上工作?和前面的E序一Pq个单的E序允许用户输入一个公基金代号q从WWW上的金融报h(hun)服务商那里取回报仗?br />
  kjava应用E序被称?spotlet?事实上,一个应用程序可以由很多 spotletl成Q但是在M旉只有一?spotlet可以昄?Palm屏幕上?在我们的例子中,我们创徏一个基?spotlet-- RequestFormSpotlet.javaQؓ(f)我们的两?spotlets子类提供用户界面。代码段 2扩展?jin)基本?RequestFormSpotlet以便得到q储存(sh)个报仗?RetrieveSpotlet也扩展了(jin)基本 RequestFormSpotletq允许储存的报h(hun)被取回(见图Q?

  代码D?
import com.sun.kjava.*;

public final class FundSpotlet extends RequestFormSpotlet {

public static void main (String args[]) {
new FundSpotlet().draw();
}

private void draw() {
initForm();
setTitle("Fund Quote Requested");
}

public void penDown(int x, int y){
if (getExitButton().pressed(x,y)){
getGraphic().playSound(Graphics.SOUND_CONFIRMATION);
System.exit(0);
}
if (getSymField().pressed(x,y))
getSymField().setFocus();
if (getGetButton().pressed(x,y)) {
quoteRequested();
}
}

private void storeQuote (String fund, String newQuote) {

int dbType = 0x46554e44;
int dbCreator = 0x43415454;
com.sun.kjava.Database quoteDB;

try {
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
if (!quoteDB .isOpen()) {

com.sun.kjava.Database.create(0, "MutualFundQuotes",
dbCreator, dbType, false);
quoteDB = new com.sun.kjava.Database(dbType,
dbCreator, com.sun.kjava.Database.READWRITE);
}
byte[] data = (fund + "#" + newQuote).getBytes();
quoteDB.addRecord(data);
quoteDB.close();
}
catch (Exception recordException) {
System.out.println("Unable to store quote and/or use
Mutual Fund Quote database.");
}

}

private void getAndDisplayQuote() {
String fundSymbol = getSymField().getText();
if (fundSymbol.length() > 0) {
String theQuote = QuoteService.getQuote(fundSymbol);
if (theQuote != null) {
storeQuote(fundSymbol, theQuote);
message(theQuote);
}
else
message("No quote. Check Symbol");
}
}

private void quoteRequested() {
message("");
getGraphic().playSound(Graphics.SOUND_STARTUP);
if ((getSymField().getText().length() > 0)) {
getAndDisplayQuote();
} else
{
message("Symbol required!");
}
}

}


  ?RequestFormSpotletE序中,cM?MIDP中的 Display对象Q单独的 Graphics理许多 spotlet用户界面昄。它考虑C(jin)屏幕?x)被清除Q显C界会(x)被徏立?不象 MIDletQ没有屏q或d对象来让我们d用户界面组Ӟ 取而代之的是按钮、文本字D늭{,直接描画?spotlet上?paint()Ҏ(gu)利用囑Ş环境从独一无二?Graphics在屏q上昄组件?br />
  我们的MIDPE序?QuoteServicecȝ大部分可以重C用?因ؓ(f) kjava没有?MIDP中HttpConnectionq样特定的连接器界面Q所以我们必d用更多标准的一般的q接器结构表单获?HTTP链接?Z(jin)做到q一点,使用代码D?3中的代码替换 getQuotePage()Ҏ(gu)。注意注意?ConnectorQ就像在 MIDP中我们?HttpConnection一栗?br />
  代码D?
private static String getQuotePage(String symbolString) {
StringBuffer quotePage = new StringBuffer();
int ch;
try {
InputStream in = Connector.openInputStream (
"testhttp://someurl/some_application?page=++&mode=fund&symbol="+
symbolString);
while ((ch = in.read()) > 0) {
quotePage.append((char)ch);
}
in.close();
return quotePage.toString();
} catch (IOException ex) {
System.out.println("Exception reading quote from
  HTTP Connection");
 return null;
 }
}


  Palm讑֤q泛利用数据库, 你的 Palm中的通讯ѝ备忘录和记事本应用E序都与数据库有兟?kjavaE序包提供了(jin)一个非常小?Databasec,不仅可以创徏q保持应用程序数据,而且可以讉K现有的数据库?如果你熟(zhn)?Palm数据库,你可能会(x)?kjava DatabasecL供的功能和信息感到失望?然而,请再ơ记住, kjava只是一个演C的版本?br />
  在我们的例子中,我们?spotlet讉K一?Palm数据?(如果不存在的话,则创Z个新的数据库Q来储存公基金报仗每?Palm数据库都必须有名字、创?ID (一?Palm登记的唯一的标识号 ) 和一个指定到某个单独应用E序的类型号?试图打开数据库要通过试创徏一个带?ID信息的数据库实例来实现?p MIDP RecordStoreQ记录被dq?kjava数据库,通过把一个字节数l当成记录添加到数据库中的Ş式?br />

  W五?再谈谈一些J2ME规范

  ?J2ME内还有很多子规范Q?J2ME的重要的部分如下QPersonalJava、K虚拟?(KVM)、Java嵌入服务器以?PersonalJava的两个扩展规范:(x) JavaPhone?JavaTV应用E序接口?你可以想象, JavaPhone是一个定位于无线甉|能电(sh)话和互联|络可视?sh)话的应用程序接口,?JavaTV则满x(chng)盒?jng)场的需求?br />
  下面我想详细的谈一谈以上的规范Q?br />
  1、PersonalJava

  PersonalJava应用E序环境目标?Webq接消费讑֤----常常执行来自|络的小应用E序。问题是 PersonalJava如何适合 J2ME的配|和表方案?{案?PersonalJava被包容q?Connected Device Configuration中,最l将被定义ؓ(f) Personal表,卛_面所谈到的Personal表?br />
  另一斚wQ有一D|间将有两?Java应用E序接口为嵌入开发世界服务:(x) PersonalJava?EmbeddedJava?PersonalJava偎依?J2ME大伞之下Q?可ؓ(f)什?EmbeddedJava不呢Q?EmbeddedJava不和 PersonalJava同在 J2ME内,是因为在 PersonalJava?EmbeddedJava应用E序之间有一个基本的差别?PersonalJava应用E序期望q接到某cȝl中下蝲q执行小应用E序?按照q种观点Q?PersonalJava讑֤是一般用途的消费讑֤Q?它们的能力可以被扩展?br />
  相比之下Q?EmbeddedJava讑֤则惨?jin)点?它们执行的功能都非常具体的,基本没有必要提供下蝲新的代码?EmbeddedJava讑֤的能力?HenceQ?PersonalJava讑֤使用可扩?Java应用E序接口Q?而EmbeddedJava讑֤则没有,因ؓ(f)没有必要使用?br />
  PersonalJava可以以两UŞ式得刎ͼ(x) 由原码Ş式的Q提供给那些Ҏ(gu)PersonalJavaUL到其他设备感兴趣的开发者,那些已经?PersonalJavaUL到某个具体的操作pȝ和处理机的组l提供二q制形式?PersonalJava环境。有兴趣探烦(ch) PersonalJava的开发者如果没有二q制q_也可以?PersonalJava模拟环境 ( PJEE )?q个模拟器运行于 Solaris/SPARC?WindowsQƈ且在许多配置中可用?q些多种多样的配|基于?look and feel”和cd支持 (环境是否提供 PersonalJava规范中规定的最低限度的或最大的cdQ。PJEE包括cLӞ一个应用程?launcher和一?appletviewer (两者都是ؓ(f)?jin)调试功能ƈ使其最优化Q和其它的附带的文g (例如字体叙述文g)?br />
  J2ME家族的另一位成?JavaCheck实用E序Q提供了(jin) PersonalJava的补充支持?你把应用E序传过 JavaCheckQ它?yu)告诉你你的应用E序在一?PersonalJava环境中能否顺利地执行?JavaCheck(g)查类之间的依赖关p,如果应用E序调用?jin)一个在 PersonalJava不可用的应用E序接口Q它?yu)׃?x)l出一个警报信受?(据我所知,目前有两UJavaCheck的版本可用,一个是用于(g)?PersonalJava 1.0版应用程序,另一个用于检?1.1.x版程序?当前?PersonalJava应用E序接口规范?1.2Q用于这一版本?JavaCheckq没有?读者请去Sun相关|站ȝ看( http : file://java.sun.com/products/personaljavaQ?br />
  2、KVM

  前面我也说过QKVM是用?J2MEq_最的虚拟机,q且是用于CLDC配置的虚拟机。可是J2ME应用E序q不一定非要?KVMQJ2ME技术可以用Q何虚拟机Q不q至应当有 KVMq样的功能?br />
  Z(jin)满ZKVM的设备一般只有狭的内存I间和有限的处理能力的事实, KVM使用 C~写 (它不是现有的VM改进?jin)的以后的品?j)?此外Q?KVM是模块化的, 也就是说Q它是由模块构徏的,当某个模块实C(jin)预先讑֮的目标后Q就可以很容易地把这一模块卸蝲?可选的某块包括Q?大的数据cd ( long?float?double )Q多l数l、类文g验证{?br />
  KVM的本地界面以M性ؓ(f)原则构徏Q所以在KVM中Q务切换不依赖g产生的记时器中断Q因此在q种意思上来说不是抢先式。Q务切换发生在虚拟机执行了(jin)一个预讄L(fng)字节码之后?q且Q?KVM的无用单元收集利用一个标记清扫(mark and sweep)法来实现无用单元释放?因此Q对象引用是直接的,像标准 Java一栗?

  当然Q除?jin)虚拟机以外q有许多可用的执行环境,在小型设备中Q虚拟机必须要么被扩展,要么在附加工具协助下提供一个更加完整的q行期环境,正是q个原因Q?KVM需要附带的工具Q比如说Q?JavaCodeCompact工具提供?jin)预链接和预加蝲c, 允许Javac被直接地链接进虚拟Z?Q设备上所有的应用E序使用的类 can直接地嵌入虚拟机。)(j)

  KVM一个可选的附g是 Java Application Manager ( Java应用E序理器,U?JAM )。JAM的工作就是处理下载、安装、执行和卸蝲 CLDC讑֤上的应用E序的细节问题,因ؓ(f)资源有限Q在CLDC讑֤上有可能不存在这些功能。JAM也处理更新安装应用程序的操作?如果更新q程p|Q它甚至可以重新使用旧的应用E序?)

  3、Java Embedded ServerQJava嵌入服务器)(j)

  Java Embedded ServerQ?Java嵌入服务器,U?JESQ,?PersonalJava基础上徏立,是一个用于嵌入式|络讑֤的运行期环境。ؓ(f)?jin)理?JESQ你必须理解两个核心(j)概念Q服务和服务I间l构。后者是前者的容器。服务程序是q行于一?JES服务器上的组件化E序Q服务空间结构是为服务程序提供生命周?支持的环境?br />
  技术上_(d)服务E序是界面的实现Q事实上Q它是一个实现特定活动的Javac集合。比如说Q假如把 JES配置Z个家庭的气候控制系l的服务器,可以把从模数转换器读到的温度数据放进一个数据组件程序中。我可以称q个lg为ReadThermostats服务E序?

  ?JES的领域,服务的封装媒介称?bundle。简单地_(d)bundle是一个带有特D内容的JAR文g。服务程序和bundle之间有一对一关系Q一个bundle带有一个服务程序。服务程序和 bundle之间有一对一关系Q一?bundle带有一个服务程序。可q也不一定,一?bundle可以讄多个服务E序索引 (注意Q?JES提供的所有的核心(j)服务Q每?bundle中只有一?)?

  正如前面提到的那P服务I间的一工作就是管理服务程序的生命周期Q这个工作的很大的部分包括解x(chng)务隶属关pRbundle内容的一个重要的部分是bundle服务的依赖信息。所以,当服务空间打开一个bundle安装它的服务Ӟ服务I间可以确定外部需要什么服务。而且Q一个服务的依赖关系q不是静(rn)止不变的Q它们可以随某些事g改变。比如说当服务程序更新时的变化就是一个很好的例子。一个服务的新的版本可以d或去除依赖关pR服务空间跟tƈ解决q样的动态依赖关pR如果服务空间处理所有服务程序的生命周期Q这暗CZ(jin)服务I间被赋予知晓一切的能力Q那是_(d)它能够推论结构、依赖、安装的l微差别{所有它负责的服务。服务空间通过?bundle内伴随服务的 Java代码模块处理一些Q务,q些模块被称?wizardQ向|(j)。JES向导是根据它们完成的d命名的:(x)

  Dependencies -向导告诉调用者一个bundle依赖关系是什么?

  Installer-向导处理bundle中服务的安装和删除操作?

  Activator -向导知道如何启动和终止服务?

  Updater -向导控g更新bundle中的服务?更新向导不仅知道更新一个服务,而且知道在何时和什么情况下更新服务?)

  About -q个向导Q就像它名称意味的那Pq回关于 bundle内容的信息?

  Dispatcher -q是一U元向导Qmeta-wizardQ。服务空间调用dispatcher向导定位一个bundle的其他向对{?

  当一?JES服务器启动的时候,服务I间q不是完全没有启动服务。JES定义一l核?j)服?可选)(j)Q这些都是Q?JES服务器的l成部分。这些核?j)服务包含?x)

  HTTP服务

  日志 -记录错误和事件日?
  
  日期 -_到秒的日?旉服务
  
  q接理?-提供|络服务和Socketl定Q也处理q接接收?

  U程理?-理服务器提供的U程。thread理器支持线E池q允许有效用线E上界的规范?

  计划E序 -提供未来的事件计划安?(可用于告诉服务器某某动作必须在某某事件发?)

  RMI

  SNMP

  控制?-提供q程理服务器功?

  Z HTTP的远E应用程序接口实?

  Z RMI的远E应用程序接口实?
 
  如果你把服务I间l构当成 JavaBean中的容器的话Q?JES变得容易理解了(jin)。在q种cL关系中,服务E序q?JavaBean。那么,正象lg容器提供一个环境供 JavaBeans实例化、运行一P服务I间是以实例化的服务的聚集地。服务空间管理安装、实例化、执行、终止以?qing)卸载服务;它也提供应用E序接口供服务交互作用?


zjw_albert 2006-07-07 14:57 发表评论
]]>
[转帖]J2MEE序开发全方位基础讲解汇?/title><link>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57130.html</link><dc:creator>zjw_albert</dc:creator><author>zjw_albert</author><pubDate>Fri, 07 Jul 2006 06:27:00 GMT</pubDate><guid>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57130.html</guid><wfw:comment>http://www.tkk7.com/zjw-albert/comments/57130.html</wfw:comment><comments>http://www.tkk7.com/zjw-albert/archive/2006/07/07/57130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjw-albert/comments/commentRss/57130.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjw-albert/services/trackbacks/57130.html</trackback:ping><description><![CDATA[ <u> <font color="#800080"> (tng)[转帖]J2MEE序开发全方位基础讲解汇?/font> </u> <div id="s0aygiq" class="postText"> <p>一、J2ME中需要的Java基础知识<br /> (tng) (tng) (tng) (tng) (tng) (tng) 现在有大部分人,都是从零开始学J2ME的,学习(fn)J2ME的时候,L从Java基础开始学?fn),而且现在讲Java基础的书c中都是以J2SE来讲基础Q这q学习(fn)造成?jin)一些不必要的麻?ch),下面J2ME中用到的和不需要的Java基础知识做一个简单的说明?br /> (tng) (tng) (tng) (tng) (tng) (tng) J2ME中用到的Java基础知识Q?br />   (tng) 1、Java语法基础Q包括基本数据类型、关键字、运符{等<br />   (tng) 2、面向对象的思想Q类和对象的概念Q承和多态等{?br />   (tng) 3、异常处?br />   (tng) 4、多U程<br />  J2ME中没有用到的Java基础知识Q?br />   (tng) 1、JDK中javac和java命o(h)的?br />   (tng) 2、Java基础中的很多cdJ2ME中没有,或者类中的Ҏ(gu)做了(jin)大量的精。所以徏议在J2ME中熟(zhn)类库?br />   (tng) 3、Applet、AWT、Swingq些知识在J2ME中根本用不到?br />  单说q么多,希望学J2ME的朋友们能少C些弯路,不之处希望大家U极指正和补充?/p> <p>二、J2ME中暂时无法完成的功能<br />  列一些J2ME中暂时无法完成的功能Q希望大家能U极补充Q?br />   (tng) 1、在手机中不更改代码实现ULQ主要指游戏?br />   (tng) 2、动态修Ҏ(gu)钮文字?br />   (tng) 3、在Canvas上接受中文输入?br />   (tng) 4、操作本地资源、例如地址本、已收短信息{?br />   (tng) 5、制作破坏性的手机病毒?br />   (tng) 6、其他等待大家来补充?/p> <p>三、J2ME的跨q_?br />  J2ME技术源于JavaQ所以也hJVM的优势,可以在支持Java的^Cq行ULQ但是现在的J2ME技术在跨^C却做的很p糕Q我们来单看一下原因:(x)<br />  1、手机的屏幕寸不一Q?br />  q个主要在界面制作上。如果你使用的是高用户界面Q比如你做的是应用开发或者用L(fng)陆、用h册这L(fng)通用功能Ӟ一般没有什么问题?br />  如果你用的是低U用L(fng)面,比如你做的是游戏Q那么你需要考虑q个问题?sh)(jin)?br />  2、厂商的扩展API不统一Q?br />  例如Nokia的扩展APIcdUIpdQ在别的手机上或者没有实玎ͼ或者包名不同等{?br />  3、手机^C实现的bugQ?br />  例如Nokia?650在实现双~冲上有bugQ那么在q种机型上运行的软g׃能用双~冲。其他NOKIA上的一些bugQ可以参看:(x)<a >http://blog.csdn.net/Mailbomb/archive/2005/03/24/329123.aspx</a><br />  4、手机性能问题?br />  不同手机的可用内存、最大jar文g都有要求Q例如Nokia S40的大部分手机支持的最大jar文g?4KQ最大可用内容ؓ(f)210K?br />  所以现在的手机软gQ特别是游戏都提供支持的机型列表Q也才有?jin)手机游戏移植h员的存在?/p> <p>四、学?fn)J2ME可以从事的工作种c?br />  现在J2ME技术可以说相当的火_(d)q里介绍一些学好了(jin)J2ME之后可以从事的工作的U类Q?br />  1、J2ME游戏开发h?br />  Ҏ(gu)游戏{划或者文档要求,在某U特定的机型(以Nokia S40或S60居多)开发游戏程序?br />  q是现在大部分J2MEE序员(sh)事的工作?br />  需要熟l掌握:(x)高用户界面、低U用L(fng)面、线E,如果是网l游戏,q需要熟l网l编E?br />  2、J2ME应用开发h?br />  现在的移动应用还?sh)是很多Q但是还是出C(jin)一些,特别是移动定位以?qing)移动商务相关的内容?br />  需要熟l掌握:(x)高用户界面、线E和|络~程?br />  3、J2ME游戏UL人员<br />  参照源代码,可以在一个^C可以q行的游戏移植到其他q_上去。例如将Nokia S40的游戏移植到S60上,或者烦(ch)qT618{等?br />  主要是控制屏q坐标,有些可能需要替换一些API?br />  需要熟(zhn)各q_之间的差异以?qing)相关的技术参敎ͼ比如屏幕大小、最大jar文g寸{等?/p> <p>五、J2MEE序设计的几个原?br />  1、用面向对象编E?br />  虽然使用面向q程~程可以减小文g的尺寸,但是Z(jin)以后l护的方便和利于扩展Q还是要使用面向对象~程?br />  2、用MVC模式<br />  模型、界面和控制分离。现在很多的E序三者合一Q但是如果你做的E序比较大的话,q是你进行分R?br />  3、自动存储用戯?br />  使用RMS来存储用L(fng)信息Q例如存储用户上ơ输入的用户名、密码、用户对于系l的讑֮{,q样不仅可以减少用户的输入,而且对用户友好。很多程序甚臛_?jin)自动登陆等?br />  4、一些系l设|允许用户关闭。如背景音乐、背景灯昄{?br />  5、将低用户界面的绘制动作放在一个独立的U程里面厅R?br />  6、在需要大量时间才能完成的工作Ӟl用户一个等待界面?/p> <p>六、从模拟器到真机试<br />  对于J2ME开发者来_(d)模拟器给我们带来?jin)很多方便,比如可以在模拟器中调试程序以及(qing)很方便的察看程序的效果Q但是模拟器也给我们带来?jin)一些问题,比如模拟器实现的bug{等Q所以进行真机测试是必须的?br />  1、ؓ(f)什么要q行真机试Q?br />  因ؓ(f)模拟器程序可能存在bugQ以?qing)真机的性能有限Q所以必进行真机测试?br />  2、如何将E序传输到机器中Q?br />  程序传输到机器中有如下方式Q?br />   (tng) a) OTA下蝲<br />   (tng) b) 使用数据U传?br />   (tng) c) U外传输<br />   (tng) d) 蓝牙<br />  你可以根据条Ӟ选择合适的方式?br />  3?真机试主要什么?<br />  真机试的内容很多,主要试以下几个斚wQ?br />   (tng) a) E序的功?br />   (tng) b) E序的操作性,是否易操?br />   (tng) c) E序的大?比如Nokia S40pd的手机大部分接受的最大文件尺ؓ(f)64K<br />   (tng) d) E序q行速度Q速度是否可以忍受?/p> <p>七、从WTK到厂商SDK<br />  对于J2ME爱好者来_(d)基本上大安是从SUN的WTK(J2ME Wireless Toolkit)开始的Q但是对于实际应用来_(d)仅仅使用WTK是远q不够的Q所以在学习(fn)q程中,必须完成从WTK到SDK的跨?br />  1、厂商SDK的下载地址Q?br />  <a >http://blog.csdn.net/Mailbomb/archive/2005/01/01/236606.aspx</a><br />  2、厂商SDK和W(xu)TK有什么不同?<br />  厂商SDK最单的理解是在WTK的基上增加了(jin)自己的模拟器和自q扩展API?br />  也就是说Q你在用厂商的SDKӞ可以使用厂商的扩展类库,例如Nokia的UIcdQ和厂商自己的模拟器而已?br />  每个厂商的扩展API都不多,而且不尽相同?br />  3、如何用?<br />  有些厂商SDK的用都和W(xu)TK相同Q例如SamSung?br />  Nokia提供?jin)独立的界面来开发,但是q个界面在实际开发中使用不多?br />  4、厂商SDK的问?br />  厂商SDK实现q程中,有一些bugQ而且和真机实C一致。例如NOKIA的؜x(chng)N题等{?/p> <p>八、在J2ME中获得手机IMEI的方?br />  IMEI是Internation mobile entity identification的简Uͼ在手Z输入*#06#可以昄该数字,长度?5位,全球唯一Q永q不?x)冲H,所以可以作别用L(fng)一个标志?br />  下面是在J2ME中获得IMEI的方法:(x)<br />  1、MOTOpd的手机可以通过dpȝ的IMEI属性获得,代码如下Q?br />   (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String imei = System.getProperty("IMEI");<br />  2、SIEMENSpd的手机可以通过dpȝ的com.siemens.IMEI属性获得,代码如下Q?br />   (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String imei = System.getProperty("com.siemens.IMEI");</p> <p>?ji)、J2ME|络q接中显C问题的解决办法<br />  在网l编E中Q有些时候会(x)出现一些在没有接收到网l数据就昄界面的,造成界面昄不符合要求(例如公告昄Q会(x)先显C公告的背景囄再显C公告信息)(j)Q这里提一个简单的解决办法l大Ӟ(x)<br />  解决q种情况的方法分成三个步骤:(x)<br />  1、在需要显C的界面中,调用发送网l数据的Ҏ(gu)。每ơ显C时调用该构造方法,不调用Display的setCurrentҎ(gu)昄?br />  2、显C等待界?例如q度条等)Q给用户提示Q在q行|络q接?br />  3、在处理|络反馈的数据完以后Q调用Display的setCurrentҎ(gu)昄昄当前界面?/p> <p>十、增强J2ME的String能力——分割字W串<br />  从JDK1.4以后QStringcM新增?jin)splitҎ(gu)来实现字W串的分Ԍ但是在J2ME中却没有该方?MIDP2.0中也没有实现)Q但是在实际使用q程中,有些时候的要用到q种操作Q这里将我以前实现的一D代码和大家׃nQ?br />/**<br />* 分割字符Ԍ原理Q检字W串中的分割字符Ԍ然后取子?br />* @param original 需要分割的字符?br />* @paran regex 分割字符?br />* @return 分割后生成的字符串数l?br />*/</p> <p>private static String[] split(String original,String regex)<br />{<br /> (tng) (tng) (tng) (tng) //取子串的起始位置<br /> (tng) (tng) (tng) (tng) int startIndex = 0;<br /> (tng) (tng) (tng) (tng) //结果数据先攑օVector?br /> (tng) (tng) (tng) (tng) Vector v = new Vector();<br /> (tng) (tng) (tng) (tng) //q回的结果字W串数组<br /> (tng) (tng) (tng) (tng) String[] str = null;<br /> (tng) (tng) (tng) (tng) //存储取子串时起始位置<br /> (tng) (tng) (tng) (tng) int index = 0;</p> <p> (tng) (tng) (tng) (tng) //获得匚w子串的位|?br /> (tng) (tng) (tng) (tng) startIndex = original.indexOf(regex); <br /> (tng) (tng) (tng) (tng) //System.out.println("0" + startIndex); <br /> (tng) (tng) (tng) (tng) //如果起始字符串的位置于字符串的长度Q则证明没有取到字符串末?br /> (tng) (tng) (tng) (tng) //-1代表取到?jin)末?br /> (tng) (tng) (tng) (tng) while(startIndex < original.length() && startIndex != -1)<br /> (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String temp = original.substring(index,startIndex);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println(" " + startIndex);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //取子?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) v.addElement(temp);</p> <p> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //讄取子串的起始位置<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) index = startIndex + regex.length();</p> <p> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //获得匚w子串的位|?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) startIndex = original.indexOf(regex,startIndex + regex.length());<br /> (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) //取结束的子串<br /> (tng) (tng) (tng) (tng) v.addElement(original.substring(index + 1 - regex.length()));<br /> (tng) (tng) (tng) (tng) //Vector对象转换成数l?br /> (tng) (tng) (tng) (tng) str = new String[v.size()];<br /> (tng) (tng) (tng) (tng) for(int i=0;i <br /> (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) str[i] = (String)v.elementAt(i);<br /> (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) <br /> (tng) (tng) (tng) (tng) //q回生成的数l?br /> (tng) (tng) (tng) (tng) return str;<br />}</p> <p>十一、J2ME在低U用L(fng)面上分行昄文字<br />  在J2ME的低U用L(fng)面开发中Q经怼(x)遇到需要在Canvas上显C大量的文字Q例如关于界面、游戏说明、游戏公告等信息。如果在设计Ӟ文字的内容和长度都固定Q既不利于修改也不利于维护。下面介l一个简单的Ҏ(gu)Q实C个简单、可l护性强的方式?br />  实现Ҏ(gu)Q?br />   (tng) 1、将需要显C的所有信息做成一个字W串?br />   (tng) 2、编写一个将该字W串按照要求转换为字W串数组的方法?br />   (tng) 3、将转换后的数组以@环的方式昄在Canvas上?br />  通过q样三个步骤Q则修改昄的信息时Q只需要修改包含显CZ息的字符串即可,自己书写的方法可以按照以前的标准重新分割新的字符丌Ӏ如果需要修Ҏ(gu)行显C的字符个数Q则只需要修改自׃写的Ҏ(gu)卛_?br />  通过q样一U实现方式,可以很方便的实现昄一些比较长的文本信息,即是可变长度的字符串也没有问题?/p> <p>十二、J2ME中用记录存储系l?RMS)存储信息<br />  在MIDP中,没有文g的概念,所以永久存储一般只能依靠记录存储系l实玎ͼ关于记录存储pȝ的简介,可以参看教程Q?a >http://www-900.ibm.com/developerWorks/cn/java/j-wi-rms/index.shtml</a><br />  下面是一些记录存储系l的常用~码介绍Q?br />   (tng) 1、打开记录集:(x)<br />  打开记录集用RecordStore里面的静(rn)态方法openRecordStoreQ示例代码如下:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) RecordStore rs = RecordStore.openRecordStore(“username?true);<br />  q样打开?jin)一个名UCؓ(f)rs的记录集Q其中username录集的名Uͼ该名U可以根据需要来取,W二个参C表是否则没有时创建新的记录集Qtrue代表在该记录集不存在Ӟ创徏新的记录集,false代表不创建?br />  如果在打开记录集时Q该记录集不存在Q则抛出RecordStoreNotFoundException异常Q所以检记录集是否已创建可以用该异常?br />  注意Q记录集打开以后记得关闭?br />   (tng) 2、向记录集中写入数据<br />   (tng) (tng) (tng) (tng) (tng) 2.1增加数据<br />  向已l打开的记录集中添加数据,需要用addRecordҎ(gu)Q示例代码:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) byte[] bytes = {1,2,3};<br />   (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int id = rs. addRecord(bytes,0,bytes.length);<br />  该代码将字节数组bytes的全部内容写入到记录集中Q该Ҏ(gu)的返回gؓ(f)该信息的idQ注意:(x)id?开始,而不是从0开始?br />  你可以@环用该Ҏ(gu)向记录集中写入多条数据?br />   (tng) (tng) (tng) (tng) (tng) 2.2修改数据<br />  修改已经存在的记录集中指定id的数据,需要用setRecordҎ(gu)Q示例代码:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) byte[] bytes = {1,2,3};<br />   (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) rs. setRecord(1,bytes,0,bytes.length);<br />  以上代码的作用是字节数lbytes的全部内容写入到id?的记录集rs中?br />  该操作会(x)覆盖已有的数据?br />  说明Q有些时候,你需要将信息写入到记录集中的W一条记录中Q则可以l合以上两个Ҏ(gu)Q则W一ơ时向记录集增加数据Q以后来q行修改?br />   (tng) 3、从记录集中d数据<br />  从记录集中读取已有数据,需要用getRecordҎ(gu)Q示例代码:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) byte[] bytes = rs. getRecord(1);<br />  该代码从记录集rs中读取第一条数据,读取到的数据放在bytes数组中?br />  在读取数据时Q可以获得记录集中id的个敎ͼ可以使用getNumRecordsҎ(gu)获得<br />  l合代码为:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) int number = rs. getNumRecords();<br /> (tng) (tng) (tng) (tng) (tng) (tng) int id = 1;<br /> (tng) (tng) (tng) (tng) (tng) (tng) if(id >0 && id < number)<br /> (tng) (tng) (tng) (tng) (tng) (tng) {<br />   (tng) (tng) (tng) (tng) byte[] bytes = rs. getRecord(1);<br /> (tng) (tng) (tng) (tng) (tng) (tng) }<br />   (tng) 4、从记录集中删除记录<br />  从记录集中删除记录的Ҏ(gu)有两U:(x)逻辑删除和物理删除?br />  逻辑删除是指l删除的记录打标记?br />  物理删除是指从物理上删除该记录,但是该记录的id不能被重用,也就是说该id不会(x)被l用。例如一个记录集中有5个记录,假设你删除了(jin)id?的数据,则剩余记录的id依然????。这l便历带来了(jin)一定的ȝ(ch)?br />   (tng) 5、便历记录集<br />  便历记录集,卌问记录集中的所有数据,有两个方法,详见Q?br /><a >http://gceclub.sun.com.cn/NASApp/sme/controller/teclist?tid=0103</a><br />   (tng) 6、其他操?br />  删除记录?br />  删除记录集不同于删除记录Q需要用deleteRecordStoreҎ(gu)Q示例代码:(x) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) RecordStore. deleteRecordStore(“username?;<br />  该代码删除名UCؓ(f)username的记录集?/p> <p>十三、J2ME加密数据的一个第三方开源免费类库介l?br />  在J2ME~程中,l常遇到一些数据在存储或者传输时需要加密,下面介绍一个第三方的加密类库的一些资料:(x)<br />  加密cd的官方主:(x)<a >http://www.bouncycastle.org/</a><br />  介绍的文章:(x)<br />  中文Q?a >http://18900.motorola.com/ewa_portal/develope/jc_j2messl_5_1.jsp</a><br />  英文Q?a >http://www.javaworld.com/javaworld/jw-12-2002/jw-1220-wireless.html</a><br />  该文章的源代码包含用的一些方法?br />  备注Q因cd提供的功能比较强大,所以类库的寸比较大,最后在发布旉要将cd中不需要的cd?/p> <p>十四、如何播攑֣?br />  在J2ME中,处理声音需要用到Mobile Media API(MMAPI)Q该包是MIDP1.0的可选包Q在MIDP2.0中已l包含了(jin)q个包。所以如果你使用MIDP1.0的话Q请认你的q行环境是否支持?br />  一般手机支持的声音文g格式为wav、mid和mpg{。具体请查阅你的手机说明文档?br />  在声韛_理中Q有很多处理的方式,q里说一下最常用的情况,播放JAR文g中的wav文g?br />  播放声音文g的流E:(x)<br />   (tng) 1、按照一定的格式d声音文g?br />  播放JAR文g中的声音文g一般是声x(chng)件处理成的形式。示例代码:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) InputStream is = this.getClass().getResourceAsStream("/Autorun.wav");<br /> (tng) (tng) (tng) (tng) (tng) (tng) 其中Autorun.wav文g位于JAR文g的根目录下,如果位于别的目录Q需要加上目录名Uͼ?res /Autorun.wav?br />   (tng) 2、将d到的内容传递给播放器?br />  流信息传递给播放器,播放器按照一定的格式来进行解码操作,CZ代码Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Player player = Manager.createPlayer(is,"audio/x-wav");<br />  其中W一个参Cؓ(f)对象,W二个参Cؓ(f)声音文g的格式?br />   (tng) 3、播攑֣韟?br />  使用Player对象的startҎ(gu)Q可以将声音播放出来Q示例代码:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) player.start()Q?br />  在播攑֣x(chng)也可以设定声x(chng)攄ơ数Q可以用PlayercM的setLoopCountҎ(gu)来实玎ͼ具体可查阅API文档?br />  下面是在NOKIA S60模拟器中试通过。代码如下:(x)<br />package sound;<br />import javax.microedition.midlet.*;<br />import javax.microedition.lcdui.*;<br />import javax.microedition.media.*;<br />import java.io.*;</p> <p>public class SoundMIDlet extends MIDlet <br />{<br />  private Player player = null;<br />  /** Constructor */<br />  public SoundMIDlet() <br /> (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) InputStream is = this.getClass().getResourceAsStream("/Autorun.wav");<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) player = Manager.createPlayer(is,"audio/x-wav");<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(IOException e)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("1:" + e);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(MediaException e)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("2:" + e);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(Exception e)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("3:" + e);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) (tng) /** Main method */<br /> (tng) (tng) (tng) (tng) (tng) public void startApp() <br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if(player != null)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br />     (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) player.start();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(MediaException e)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br />     (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("4:" + e);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) (tng) (tng) /** Handle pausing the MIDlet */<br /> (tng) (tng) (tng) (tng) (tng) (tng) public void pauseApp() <br /> (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) (tng) (tng) /** Handle destroying the MIDlet */<br /> (tng) (tng) (tng) (tng) (tng) (tng) public void destroyApp(boolean unconditional) <br /> (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) }<br />}</p> <p>十五、J2ME 3D~程的一些资?br />  随着J2ME技术的发展Q以?qing)硬仉度的提升,3D游戏E序慢慢的变成LQ最q想学习(fn)q一块的~程Q所以收集了(jin)一些资料,和大家一起分享:(x)<br />  1、JSR184<br />  JSR184是Nokia公司赯的一个关?D API的规范,下蝲地址为:(x)<br />  <a >http://www.forum.nokia.com/main/1,,1_0_10,00.html#jsr184</a><br />  2、Nokia?D~程资料<br />  <a >http://www.forum.nokia.com/main/1,6566,21,00.html</a><br />  3?D引擎<br />  一个简单的开放源代码?D游戏引擎<br />  <a >http://www.j2me.com.cn/Soft_Show.asp?SoftID=19</a><br />  国内一个合作开?D引擎的项目:(x)<br />  <a >http://gceclub.sun.com.cn/NASApp/sme/jive/thread.jsp?forum=11&thread=8593</a><br />  4、一?D游戏产品<br />  <a >http://games.sina.com.cn/newgames/2004/04/040217696.shtml</a><br />  5、支?D的开发工?br />  当前一些高端的手机支持3D开发,支持3D开发的开发工具中Q通用的有SUN的J2MEWTK2.2。专用的是厂商提高的支持JSR184的SDK?/p> <p>十六?D~程——第一?DE序<br />  参考WTK2.2提供的demoQ完成了(jin)W一?DE序Q虽然很单,而且有些问题q(sh)是很清楚Q还是把代码׃n出来和愿意学?fn)J2ME 3D~程的朋友一起学?fn)?br />  关于代码的编译和q行说明如下Q?br />  1、以下代码在J2ME WTK2.2下面~译通过?br />  2、代码分Z个文Ӟ(x)First3DCanvas.java和First3DMIDlet.java?br />  3、用J2ME WTK2.2建立新的工程Q主MIDletcMؓ(f)Qfirst3d. First3DMIDlet<br />  4、将代码保存在你的工E目录下的first3d目录下?br />  5、将J2ME WTK安装目录下的apps\Demo3D\res\com\superscape\m3g\wtksamples\retainedmode\content目录中的swerve.m3g文g复制C的工E目录下的res目录下?br />  6、你的工E徏立后Q设|工E,通过WTK界面中的“设|”按钮打开讄H口Q在“API选择”中Q设|“目标^台”ؓ(f)Q自定义Q“简档”ؓ(f)“MIDP2.0”;“配|”ؓ(f)“CLDC1.1”;选中“Mobile 3D Graphics for J2ME(JSR184)”?br />  7、这样你可以编译和q行以下代码?jin)?br />  源代码如下:(x) </p> <p>// First3DMIDlet.java<br />package first3d;<br />import javax.microedition.midlet.*;<br />import javax.microedition.lcdui.*;<br />public class First3DMIDlet extends MIDlet <br />{<br /> (tng) (tng) (tng) (tng) (tng) private First3DCanvas displayable = new First3DCanvas();<br /> (tng) (tng) (tng) (tng) (tng) public void startApp() <br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Display.getDisplay(this).setCurrent(displayable);<br /> (tng) (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) (tng) public void pauseApp() {}</p> <p> (tng) (tng) (tng) (tng) (tng) public void destroyApp(boolean unconditional) {}<br />}</p> <p>// First3Dcanvas.java<br />package first3d;<br />import javax.microedition.lcdui.*;<br />import javax.microedition.m3g.*;<br />import java.util.*;<br />/**<br />* W一?DE序<br />*/<br />public class First3DCanvas extends Canvas implements Runnable <br />{<br /> (tng) (tng) (tng) (tng) (tng) /**World对象*/<br /> (tng) (tng) (tng) (tng) (tng) private World myWorld = null;<br /> (tng) (tng) (tng) (tng) (tng) /**Graphics3D对象*/<br /> (tng) (tng) (tng) (tng) (tng) private Graphics3D g3d = Graphics3D.getInstance();<br /> (tng) (tng) (tng) (tng) (tng) /**Camera对象*/<br /> (tng) (tng) (tng) (tng) (tng) private Camera cam = null;<br /> (tng) (tng) (tng) (tng) (tng) private int viewport_x;<br /> (tng) (tng) (tng) (tng) (tng) private int viewport_y;<br /> (tng) (tng) (tng) (tng) (tng) private int viewport_width;<br /> (tng) (tng) (tng) (tng) (tng) private int viewport_height;<br /> (tng) (tng) (tng) (tng) (tng) private long worldStartTime = 0;<br /> (tng) (tng) (tng) (tng) (tng) //重绘旉<br /> (tng) (tng) (tng) (tng) (tng) private int validity = 0;<br /> (tng) (tng) (tng) (tng) (tng) <br /> (tng) (tng) (tng) (tng) (tng) public First3DCanvas() <br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //启动重绘界面的线E?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Thread thread = new Thread(this);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) thread.start();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //导入3D囄<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) myWorld = (World) Loader.load("/swerve.m3g")[0];<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_x = 0;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_y = 0;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_width = getWidth();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_height = getHeight();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) cam = myWorld.getActiveCamera();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //讄cam对象<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) float[] params = new float[4];<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int type = cam.getProjection(params);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (type != Camera.GENERIC) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //calculate window aspect ratio<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) float waspect = viewport_width / viewport_height;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (waspect < params[1]) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) float height = viewport_width / params[1];<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_height = (int) height;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_y = (getHeight() - viewport_height) / 2;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) else <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) float width = viewport_height * params[1];<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_width = (int) width;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) viewport_x = (getWidth() - viewport_width) / 2;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) worldStartTime = System.currentTimeMillis();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch (Exception e) {}<br /> (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) <br /> (tng) (tng) (tng) (tng) (tng) protected void paint(Graphics g) <br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //清除背景<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g.setColor(0x00);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g.fillRect(0, 0, getWidth(), getHeight());<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //?D对象l定<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g3d.bindTarget(g);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g3d.setViewport(viewport_x, viewport_y, viewport_width, viewport_height);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) long startTime = System.currentTimeMillis() - worldStartTime;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) validity = myWorld.animate((int)startTime);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g3d.render(myWorld);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) finally <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g3d.releaseTarget();<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) }</p> <p> (tng) (tng) (tng) (tng) (tng) public void run() <br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) while(true)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //重绘囑Ş<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) repaint(viewport_x, viewport_y, viewport_width, viewport_height);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(Exception e){}<br /> (tng) (tng) (tng) (tng) (tng) }<br />}</p> <p>十七、在J2ME|络~程中用CMWAP代理<br />  在中国移动提供的|络q接中,分ؓ(f)CMNET和CMWAP两种Q其中CMNET可以无限制的讉K互联|络Q资Ҏ(gu)较贵。CMWAPcM一个HTTP的代码,只能讉K支持HTTP的应用,但是资费便宜Q稳定性比较差?br />  在实际的J2ME|络~程中,一般需要提供以CMWAP代理的方式连接网l,在J2ME中,q接的代码和直接q接有所不同Q代码如下:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) HttpConnection http = (HttpConnection)Connector.open(("<a +url</a>);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) http.setRequestProperty("X-Online-Host",ServerName);<br />  例如你需要访问的地址为:(x)<a >http://www.test.com/login/loginServlet</a>则上面的代码׃ؓ(f)Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) HttpConnection http = (HttpConnection)Connector.open(("<a + "login/loginServlet");<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) http.setRequestProperty("X-Online-Host","<a );<br />  在实际用过E中Q只需要用实际需要访问的地址的域名或者IP来代替ServerNameQ例如示例中的“www.test.com”,使用后箋(hu)的地址cM替代码中的urlQ例如示例中的“login/loginServlet”,可以实际的使用CMWAP代理来进行连接了(jin)?/p> <p>十八、J2ME中的旉处理全攻?br />  旉处理在程序开发中相当常见Q下面对于时间处理做一个简单的说明?br />  一、时间的表达方式<br />  旉在J2ME中有两种表达方式Q?br />  1、以和GMT1970q??号午?2点和现在相差的毫U数来代?br />  q种方式适合比较两个旉之间的差倹{?br />  2、以对象的Ş式来表达<br />  二、时间处理的相关c?br />  旉处理在J2ME中涉?qing)三个类Q?br />  1、Systemc?br />   long time = System. currentTimeMillis();<br />  使用该方法可以获得当前时_(d)旉的表达方式ؓ(f)上面提到的第一U?br />  2、Datec?br />   Date date = new Date();<br />  获得当前旉Q用对象的形式来进行表达?br />  3、Calendarc?br />   Calendar calendar = Calendar. getInstance();</p> <p>三、时间处理的具体操作<br />  1、以上三U表达方式的转换Q?br />  a)Systemc获得的旉转换为Date对象<br />   Date date = new Date(System. currentTimeMillis());<br />  b)Datecd的对象{换ؓ(f)Calendarcd的对?br />   Calendar calendar = Calendar. getInstance();<br />   Date date = new Date();<br />   calendar.setTime(date);<br />  2、用Calendar完成一些日期操作:(x)<br />  Calendar是时间处理中最常用也是功能最强大的类Q可以用它来获得某个旉的日期、星期几{信息?br />  获得日期Q?br />   Calendar calendar = Calendar. getInstance();<br />   …?br />   int day = calendar.get(Calendar. DATE);<br />  获得日期、年份、星期的操作和这个类伹{?br />  需要注意的是:(x)Calendar中表C月份的数字和实际相?Q即1月用数字0表示Q?月用数字1表示Q…?2月用数字11表示?/p> <p>十九(ji)、J2ME中随机数字处理全ȝ<br />  在程序中生成随机数字Q用处比较,如h工智能领域等{,q里对于在J2ME中生成随机数的操作进行一个简单的整理Q希望对大家能有帮助?br />  J2ME和J2SE不同Q不能用Mathcȝrandom来生成随机数字,只能使用java.util包的RandomcL生成随机数字?br />  1、创建Randomcd的对象:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Random random = new Random();<br />   Random random = new Random(10010010);<br />  以上两种是创建Random对象的方式,W一U用默认构造方法,和以下的代码作用完全{h(hun)Q?br />   Random random = new Random(System. currentTimeMillis());<br />  相当与用当前时间作为种子数字来q行创徏?br />  W二U方式通过自己来指定种子数字来q行创徏?br />  大家可以Ҏ(gu)需要用以上两U方式的MU?br />  2、生成随机数字:(x)<br />  创徏好了(jin)随机对象以后Q我们就可以来生成随机数字了(jin)Q?br />  生成随机整数Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int k = random.nextInt();<br /> (tng) (tng) (tng) (tng) (tng) (tng) 生成随机长整敎ͼ(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) long l = random.nextLong();<br />  3、生成指定范围的数字Q?br />  例如生成0-10之间的随机数字:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int k = random.nextInt();<br />   int j = Math.abs(k % 10);<br />  首先生成一个随机整数kQ然后用k?0取余Q最后用MathcȝabsҎ(gu)取绝对|获得0-10之间的随机数字?br />  获得0-15之间的随机数Q类|(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int k = random.nextInt();<br />   int j = Math.abs(k % 15);<br />  获得10-20之间的随机数字:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int k = random.nextInt();<br />   int j = Math.abs(k % 10) + 10;</p> <p>二十、在J2ME手机~程中用字?br />  在J2ME手机~程中,可以通过使用字体cZ—Font在低U用L(fng)面中Q获得更好的表现效果Q那么如何用FontcdQ?br />  首先Q由于手备的限制Q手Z支持的字体类型很有限Q所以在J2ME中只能用手机支持的默认字体来构造Fontcd象。下面是创徏Fontcȝ对象时用的Ҏ(gu)Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) getFont(int face,int style,int size);<br />例如Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Font font = Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font. SIZE_MEDIUM);<br />  无论哪一个参敎ͼ都只能用系l设|的数|q些数值具体的大小在不同的手机上可能不同。下面对于其中的三个参数的取值做详细的介l:(x)<br />  face参数指字体的外观Q其的取|(x)<br />  FACE_MONOSPACE——等宽字?br />  FACE_PROPORTIONAL——均衡字?br />  FACE_SYSTEM——系l字?br />  style参数指字体的样式Q其的取|(x)<br />  STYLE_BOLD——粗?br />  STYLE_ITALIC——斜?br />  STYLE_PLAIN——普?br />  STYLE_UNDERLINED——下划线<br />  STYLE_BOLD | STYLE_ITALIC——粗斜体<br />  STYLE_UNDERLINED | STYLE_BOLD——带下划U粗?br />  STYLE_UNDERLINED | STYLE_ITALIC——带下划U斜?br />  STYLE_UNDERLINED | STYLE_ITALIC | STYLE_BOLD——带下划U的_斜?br />  size参数指字体的大小Q其的取|(x)<br />  SIZE_SMALL——小<br />  SIZE_MEDIUM——中<br />  SIZE_LARGE——大<br />  通过上面的参数的|可以l合Z需要的字体对象?br />  下面是一些常用的字体操作Q?br />  1. 获得pȝ的默认字体:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Font font = Font.getDefaultFont();<br />  2. 在panitҎ(gu)内部Q假设Graphics参数的名UCؓ(f)gQ则获得当前字体的方法是Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Font font = g.getFont();<br />  3. 在panitҎ(gu)内部Q假设Graphics参数的名UCؓ(f)gQ则讄当前字体的方法是Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g.setFont(font);<br />  其中fontZ构造好的字体对象?br />  4. 在MIDP2.0中,List可以讄每行的字体格式,Ҏ(gu)是:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) list.setFont(0,font);<br />  则上面的代码是将list中的W一行设|ؓ(f)fontcd的字体?/p> <p>二十一、在J2ME手机E序开发中使用颜色<br />  在J2ME手机开发过E中Q需要经常用到颜色来q行l制Q增强程序的表现效果Q下面就介绍一下如何用颜艌Ӏ?br />  ׃J2ME技术比较简单,所以没有实C门的颜色c,而只是用RGB的概忉|代表颜色。这里简单介l一下RGB的概念,颜色是由U?Red)、绿(Green)、蓝(Blue)三原色组成的Q所以可以用这三个颜色的组合来代表一U具体的颜色Q其中R、G、B的每个数值都位于0-255之间。在表达颜色的时候,卛_以用三个数字来表达Q也可以使用一个格式如0X00RRGGBBq样格式的十六进制来表达Q下面是常见颜色的表辑Ş式:(x)<br />  U色Q?255,0,0)?x00FF0000<br />  l色Q?0,255,0)?x0000FF00<br />  蓝色Q?255,255,255)?x00FFFFFF<br />  其他颜色也可以通过上面的方式组合出来?br />  知道?jin)颜色的表达方式以后Q下面来介绍一下如何在J2MEE序中用颜Ԍ涉及(qing)的方法均在GraphicscMQ有以下几个Q?br />  1.getColor()Q?br />  获得当前使用的颜Ԍq回值是0x00RRGGBB格式的数字。例如:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int color = g.getColor();<br />  其中g为Graphicscd的对象?br />  2.setColor(int RGB)Q?br />  讄使用的颜艌Ӏ例如:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g.setColor(0x00ff0000);<br />  3.setColor(int red, int green, int blue)<br />  和上面的Ҏ(gu)作用一P例如Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) g.setColor(255,0,0);<br />  在设|了(jin)Graphics使用的颜色以后,再进行绘制的时候,可以绘制指定的颜色?jin)?/p> <p>二十二、在J2ME联网应用中获得客L(fng)的手机号?br />  在J2MEE序开发过E中Qؓ(f)?jin)一定的需要,l常需要来获得用户的手机号码,但是q个功能却在标准的J2MEcd中没有提供?br />  在用中国移动的CMWAP方式q接|络Ӟ中国Ud?x)将用户的手机号码放在一个名UCؓ(f)x-up-calling-line-id的头信息中,可以通过d该头信息Q获得用L(fng)手机L(fng)Q具体代码如下:(x)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String usermphone = http.getHeader("x-up-calling-line-id");<br />  其中h(hun)ttp是HttpConnctioncd的对象?/p> <p>二十三、用J2ME发送手机短信息<br />  在程序中Q发送短信息的方式一般有三种Q?br />  1?使用E序在网l上发送短信息Q例如各大网站的短信业务。这U方式是通过E序信息发送给q营商的|关服务器,然后通过q营商的|络发送给手机?br />  2?在计机中,通过数据U连接到手机Q然后通过手机来发送短信息。这U方式是通过使用AT指o(h)来实现。爱立信手机的AT指o(h)你可以在以下地址扑ֈQ?a >http://mobilityworld.ericsson.com.cn/development/download_hit.asp</a><br />  3?通过在手Zq行的程序来发送短信息。这个正是本文实现的方式?br />  在J2ME中,如果惛_送短信息Q需要用WMA包,MIDP2.0中已l包含,MIDP1.0中可以通过厂商提供的扩展API实现Q和W(xu)MA的类库基本一栗?br /> (tng) (tng) (tng) (tng) (tng) (tng) 下面是用WMA向指定手机号码发送短信息的一个方法,很简单。当然WMA也提供了(jin)其他的方式来发送更多的内容?/p> <p>// SMSUtil.java<br />package my.util;<br />import javax.wireless.messaging.*;<br />import javax.microedition.io.*;<br />/**<br />* 发送文本短信息的方?br />*/<br />public class SMSUtil<br />{<br /> (tng) (tng) (tng) (tng) (tng) /**<br /> (tng) (tng) (tng) (tng) (tng) * l指定号码发送短信息<br /> (tng) (tng) (tng) (tng) (tng) * @param content 短信息内?br /> (tng) (tng) (tng) (tng) (tng) * @param phoneNumber 手机L(fng)<br /> (tng) (tng) (tng) (tng) (tng) * @return 发送成功返回trueQ否则返回false<br /> (tng) (tng) (tng) (tng) (tng) */<br /> (tng) (tng) (tng) (tng) (tng) public static boolean send(String content,String phoneNumber)<br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //q回?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) boolean result = true;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) try<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //地址<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) String address = "sms://+" + phoneNumber;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //建立q接<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) MessageConnection conn = (MessageConnection)Connector.open(address);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //讄短信息类型ؓ(f)文本Q短信息有文本和二进制两U类?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) TextMessage msg = (TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //讄信息内容<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) msg.setPayloadText(content);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //发?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) conn.send(msg);<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) catch(Exception e)<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) result = false;<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //未处?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return result;<br /> (tng) (tng) (tng) (tng) (tng) } <br />}</p> <p>二十四、用简单的J2MEE序试MIDlet的生命周?br />  在MIDletE序学习(fn)中,生命周期是一个比较抽象的概念。其实生命周期就是一个简单的规定Q规定了(jin)MIDlet中的每个Ҏ(gu)Q什么时候被pȝ调用。下面是一个示例代码,在每个方法的内部都输Z条语句,可以Ҏ(gu)E序的输出结果来验证各方法被调用的顺序,具体代码如下Q?/p> <p> <br />//文g名:(x)LifeCircleMIDlet.java<br />import javax.microedition.midlet.*;<br />/**<br />* 试MIDlet的生命周?br />*/<br />public class LifeCircleMIDlet extends MIDlet<br />{<br /> (tng) (tng) (tng) (tng) (tng) /**<br /> (tng) (tng) (tng) (tng) (tng) * 默认构造方?br /> (tng) (tng) (tng) (tng) (tng) */<br /> (tng) (tng) (tng) (tng) (tng) public LifeCircleMIDlet()<br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("默认构造方?);<br /> (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) /**<br /> (tng) (tng) (tng) (tng) (tng) * 启动Ҏ(gu)<br /> (tng) (tng) (tng) (tng) (tng) */<br /> (tng) (tng) (tng) (tng) (tng) public void startApp()<br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("startAppҎ(gu)");<br /> (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) /**<br /> (tng) (tng) (tng) (tng) (tng) * 暂停Ҏ(gu)<br /> (tng) (tng) (tng) (tng) (tng) */<br /> (tng) (tng) (tng) (tng) (tng) public void pauseApp()<br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("pauseAppҎ(gu)"); <br /> (tng) (tng) (tng) (tng) (tng) }<br /> (tng) (tng) (tng) (tng) (tng) /**<br /> (tng) (tng) (tng) (tng) (tng) * 销毁方?br /> (tng) (tng) (tng) (tng) (tng) * @param b <br /> (tng) (tng) (tng) (tng) (tng) */<br /> (tng) (tng) (tng) (tng) (tng) public void destroyApp(boolean b)<br /> (tng) (tng) (tng) (tng) (tng) {<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) System.out.println("destroyAppҎ(gu)"); <br /> (tng) (tng) (tng) (tng) (tng) } <br />}<br />  在J2WTK中运行该E序Ӟ可以使用览器中的“MIDlet”菜单中的暂停和恢复菜单Q模拟暂停事件?/p> <p>二十五、用OTA来发布你的程?br />  众所周知QJ2MEE序发布的Ş式主要有QOTA、数据线传输、红外和蓝牙传输{。这里简单说说如何通过OTA来发布你的程序?br />  OTA是Over The Air的简写,也就是通过|络下蝲Q这是主要的发布形式之一。现在的癑֮都是采用这UŞ式?br />  使用OTA来发布程序,需要如下几个步骤:(x)<br />  1、在你的WEB服务器上d对于jad和jar文g的MIME支持?br />  后缀?jad<br />  MIMEcd:text/vnd.sun.j2me.app-descriptor<br />  后缀?jar<br />  MIMEcd:application/java-archive<br />  2、发布WML面Q?br />  例如你的jar文g名test.jadQ则最单的下蝲面是:(x)<br />  <?xml version="1.0"?> <br />  <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" <br />  "<a > <br />  <wml> <br />  <card id="card1" title="Download Midlet"> <br />  <a href="test.jad">test</a> <br />  </card> <br />  </wml> <br />  你可以将以上代码保存在WEB服务器上Q例如保存(sh)ؓ(f)text.wml<br />  3、修改jad文gQ?br />  在jad文g中增加 MIDlet-Jar-URL: <a href="http://domain/directory/test.jar">http://domain/directory/test.jar</a><br />  其中?a href="http://domain/directory/test.jar">http://domain/directory/test.jar</a>Z的jar文g的\径?br />  l过上面的设|,你就可以你的wml面路径作ؓ(f)你的WAP下蝲面发布?jin)。用户只需要在手机上输入这个\径就可以讉K和下载你的程序了(jin)?br /><strong>作者BlogQ?/strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" target="_blank">http://blog.csdn.net/Mailbomb/</a></p> </div> <img src ="http://www.tkk7.com/zjw-albert/aggbug/57130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjw-albert/" target="_blank">zjw_albert</a> 2006-07-07 14:27 <a href="http://www.tkk7.com/zjw-albert/archive/2006/07/07/57130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现q接?/title><link>http://www.tkk7.com/zjw-albert/archive/2006/06/06/50898.html</link><dc:creator>zjw_albert</dc:creator><author>zjw_albert</author><pubDate>Tue, 06 Jun 2006 12:36:00 GMT</pubDate><guid>http://www.tkk7.com/zjw-albert/archive/2006/06/06/50898.html</guid><wfw:comment>http://www.tkk7.com/zjw-albert/comments/50898.html</wfw:comment><comments>http://www.tkk7.com/zjw-albert/archive/2006/06/06/50898.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjw-albert/comments/commentRss/50898.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjw-albert/services/trackbacks/50898.html</trackback:ping><description><![CDATA[通常商业数据库JDBC驱动都会(x)提供自已的数据库q接池管理器Q无需自己制做?<br />无论如何Q这里给Z个简单实?<br /><br />实现q接池的关键点:(x) <br />1. (tng)单实?<br />2. (tng)由实现类来管理数据库q接Q包括连接,h <br />3. (tng)重蝲java.sql.Connection的close功能。当客户E序调用close时不是真正的断开q接Q而是连接归q连接池理器?<br />4. (tng)数据库属性独立于理器本w?<br /><br />可选:(x) <br />1. (tng)实现javax.sql.PooledConnection <br />2. (tng)实现javax.sql.DataSource <br />3. (tng)实现javax.sql.ConnectionPoolDataSource <br /><br />一个简单实玎ͼ(x) <br />import (tng)java.io.*; <br />import (tng)java.util.*; <br />import (tng)java.sql.*; <br /><br />public (tng)class (tng)ConnectionPool (tng)implements (tng)Runnable (tng){ <br /> (tng) (tng) (tng) (tng)static (tng)String (tng)configFileName; (tng)// (tng)?/connection-pool.properties <br /> (tng) (tng) (tng) (tng)static (tng)Properties (tng)config; <br />private (tng)static (tng)List (tng)list (tng)= (tng)null; <br /> (tng) (tng) (tng) (tng)private (tng)static (tng)boolean (tng)isCreate (tng)= (tng)false; <br /> (tng) (tng) (tng) (tng)/** <br /> (tng) (tng) (tng) (tng) (tng)* (tng)实现单实例,关键? <br /> (tng) (tng) (tng) (tng) (tng)* (tng)@throws (tng)SQLException <br /> (tng) (tng) (tng) (tng) (tng)*/ <br />public (tng)ConnectionPool (tng)() (tng)throws (tng)SQLException (tng){ <br />if (tng)(list (tng)== (tng)null) (tng)init (tng)(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(!isCreate) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Thread (tng)thread (tng)= (tng)new (tng)Thread(this); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)thread.run(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)isCreate (tng)= (tng)true; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br />} <br /><br /> (tng) (tng) (tng) (tng)public (tng)synchronized (tng)Connection (tng)getConnection (tng)() (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(list (tng)== (tng)null) (tng)return (tng)null; <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)LI闲的连?<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)list.size(); (tng)i (tng)++){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ConnectionWrap (tng)conn (tng)= (tng)(ConnectionWrap)list.get(i); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(conn.free) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)conn.free (tng)= (tng)false; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)conn.start (tng)= (tng)System.currentTimeMillis(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)conn; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)没有I闲的连接则自动扩展 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)step (tng)= (tng)I(yng)nteger.parseInt(config.getProperty("step")); (tng)// (tng)取得自动扩展的步?<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.addConnection(step); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)(ConnectionWrap)list.get(list.size() (tng)- (tng)step (tng)- (tng)1); <br /> (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng)public (tng)void (tng)run (tng)() (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)long (tng)interval (tng)= (tng)Long.parseLong(config.getProperty("interval")); (tng)// (tng)扫描旉 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)while (tng)(true) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Thread.sleep(interval); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(Exception (tng)e) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)出错处理 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)scan (tng)(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng)/** <br /> (tng) (tng) (tng) (tng) (tng)* (tng)关键?Q管理连接。一些超时的q接h <br /> (tng) (tng) (tng) (tng) (tng)*/ <br /> (tng) (tng) (tng) (tng)private (tng)void (tng)scan (tng)() (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)timeout (tng)= (tng)I(yng)nteger.parseInt(config.getProperty("timeout")); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)list.size(); (tng)i (tng)++) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ConnectionWrap (tng)conn (tng)= (tng)(ConnectionWrap) (tng)list.get(i); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(conn.start (tng)>; (tng)0) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)time (tng)= (tng)System.currentTimeMillis() (tng)- (tng)conn.start; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(time (tng)>;= (tng)timeout) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)conn.close(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)initCount (tng)= (tng)I(yng)nteger.parseInt(config.getProperty("init-count")); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(list.size() (tng)>; (tng) (tng)initCount) (tng){ (tng)// (tng)恢复到初始连接数 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)list.size() (tng)- (tng)1; (tng)i (tng)>; (tng)initCount; (tng)i (tng)--) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ConnectionWrap (tng)conn (tng)= (tng)(ConnectionWrap) (tng)list.get(i); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(conn.free) (tng){ (tng)// (tng)真正地断开q接 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)conn.conn.close(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(SQLException (tng)ignore){} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)list.remove(conn); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng)} <br /><br />private (tng)void (tng)init (tng)() (tng)throws (tng)SQLException (tng){ <br />config (tng)= (tng)readConfig (tng)(); <br />createConnectionPool (tng)(config); <br />} <br /><br /> (tng) (tng) (tng) (tng)/** <br /> (tng) (tng) (tng) (tng) (tng)* (tng)d配置文g <br /> (tng) (tng) (tng) (tng) (tng)* (tng)@return (tng)java.util.Properties <br /> (tng) (tng) (tng) (tng) (tng)* (tng)@throws (tng)SQLException <br /> (tng) (tng) (tng) (tng) (tng)*/ <br />private (tng)void (tng)readConfig (tng)() (tng)throws (tng)SQLException (tng){ <br />InputStream (tng)in (tng)= (tng)null; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)in (tng)= (tng)new (tng)FileInputStream (tng)(configFileName); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)config (tng)= (tng)new (tng)Properties (tng)(); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)config.load(in); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(IOException (tng)ioe) (tng){ (tng)// (tng)出错处理 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw (tng)new (tng)SQLException (tng)(ioe.getMessage()); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)finally (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(in (tng)!= (tng)null) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){ (tng)in.close(); (tng)} (tng)catch (tng)(IOException (tng)ignore) (tng){} <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br />} <br /><br /> (tng) (tng) (tng) (tng)private (tng)void (tng)createConnectionPool (tng)() (tng)throws (tng)SQLException (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)driverName (tng)= (tng)config.getProperty("driver-name"); <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)initCount (tng)= (tng)I(yng)nteger.parseInt(config.getProperty("init-count")); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)maxCount (tng)= (tng)I(yng)nteger.parseInt(config.getProperty("max-count")); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Driver (tng)driver (tng)= (tng)Class.forName(driverName); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)addConnection (tng)(initCount); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(Exception (tng)e) (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throw (tng)new (tng)SQLException (tng)(e.getMessage()); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /> (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng)private (tng)void (tng)addConnection (tng)(int (tng)count) (tng)throws (tng)SQLException (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(list (tng)== (tng)null) (tng)list (tng)= (tng)new (tng)ArrayList (tng)(count); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)url (tng)= (tng)config.getProperty("url"); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)user (tng)= (tng)config.getProperty("user"); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)password (tng)= (tng)config.getProperty("password"); <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)count; (tng)i (tng)++) <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)list.add(new (tng)ConnectionWrap (tng)(url, (tng)user, (tng)password)); <br /> (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng)class (tng)ConnectionWrap (tng)implements (tng)Connection (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Connection (tng)conn (tng)= (tng)null; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)boolean (tng)free; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)long (tng)start; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ConnectionWrap (tng)(String (tng)url, (tng)String (tng)user, (tng)String (tng)password) (tng)throws (tng)Exception (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Connection (tng)conn (tng)= (tng)DriverManager.getConnection(url, (tng)user, (tng)password); <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)free (tng)= (tng)true; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)/** <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)* (tng)q里关键?Qƈ不真正断开q接Q而是归还l管理器 <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)* (tng)@return <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)* (tng)@throws (tng)SQLException <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)*/ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)public (tng)boolean (tng)close (tng)() (tng)throws (tng)SQLException (tng){ <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)free (tng)= (tng)true; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)start (tng)= (tng)0; <br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} <br /><br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)其他java.sql.Connection的方?<br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)... <br /> (tng) (tng) (tng) (tng)} <br />} <br /><br />配置文gCZ <br />driver-name (tng)= (tng)oracle.jdbc.driver.Driver <br />url (tng)= (tng)jdbc:oracle:thin:@host:1521:employee <br />user (tng)= (tng)scott <br />password (tng)= (tng)tiger <br />timeout (tng)= (tng)60000 (tng)# (tng)一分钟 <br />init-count (tng)= (tng)10 <br />step (tng)= (tng)5 <br />interval (tng)= (tng)1000 (tng)# (tng)1U?<br />... <br /><br />以后在客L(fng)可以q么调用 <br />ConnectionPool (tng)pool (tng)= (tng)new (tng)ConnectionPool (tng)(); <br />Connection (tng)conn (tng)= (tng)null; <br />try (tng){ <br />conn (tng)= (tng)pool.getConnection (tng)(); <br />// (tng)其他操作 <br />} (tng)finally (tng){ <br />if (tng)(conn (tng)!= (tng)null) (tng)conn.close (tng)(); <br />} <br /><br />限于幅Qjavax.sql.DataSource, (tng)javax.sql.ConnectionPoolDataSource{就不一一列出?br /><img src ="http://www.tkk7.com/zjw-albert/aggbug/50898.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjw-albert/" target="_blank">zjw_albert</a> 2006-06-06 20:36 <a href="http://www.tkk7.com/zjw-albert/archive/2006/06/06/50898.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的网l功能与~程Q{载)(j)http://www.tkk7.com/zjw-albert/archive/2006/03/20/36282.htmlzjw_albertzjw_albertMon, 20 Mar 2006 04:28:00 GMThttp://www.tkk7.com/zjw-albert/archive/2006/03/20/36282.htmlhttp://www.tkk7.com/zjw-albert/comments/36282.htmlhttp://www.tkk7.com/zjw-albert/archive/2006/03/20/36282.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/36282.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/36282.htmlJava?/font> 功能与编E?br />徐迎?br />(上v大学计算中心(j)25Q?
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
摘?tng) (tng)要QJava语言是Internet上最热门的编E语aQ本文针?br />
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)Java?/font>
功能Q对Java?/font> 上获取图象、声韟?br />
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)HTML文档?qing)文本文件等~程Ҏ(gu)作了(jin)初步的介l,?br />
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)时介l了(jin)动态获?/font>
上资源的Ҏ(gu)作了(jin)介绍。文?br />
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)提供?jin)大量简明易懂的实例?br />
关键词:(x)JavaQInternetQ?/font>
 (tng) (tng) (tng) (tng)Java语言是Internet上新兴的~程语言Q对Java的特性以?qing)?br />
本的~程Ҏ(gu)已有很多文章作过介绍。但是,q大Java爱好者更希望

?jin)解Java更深一步的~程Ҏ(gu)Q本文就Java?/font>
功能?qing)其~程Ҏ(gu)

作一初步的介l?br />
 (tng) (tng) (tng) (tng)Z(jin)方便初次接触Java的读者,本文先就Java~程的一些常?br />
作简单介l?br />


 (tng) (tng) (tng) (tng)一、Java~程?br />


 (tng) (tng) (tng) (tng)1. ~程环境Q?br />


 (tng) (tng) (tng) (tng)对于大部分读者,以下的配|是较ؓ(f)l济的一U选择Q?br />
操作pȝ Win95

~译软g JDK1.01

览软g Netscape2.0以上Q?2位)(j)



 (tng) (tng) (tng) (tng)2. ~程Ҏ(gu)Q?br />


 (tng) (tng) (tng) (tng)先用文本~辑器如Edit、NotePad{输入JavaE序Q以.java?br />
文g名后~存盘?br />
 (tng) (tng) (tng) (tng)再执行命令行Q“Javac 文g名”来~译JavaE序。编译后生成

后缀?class的字节码文g?br />
 (tng) (tng) (tng) (tng)最后,如果是Java ApplitcationQ则执行命o(h)行:(x)“Java ?br />
节码文g名”来q行JavaE序?br />
 (tng) (tng) (tng) (tng)如果是Java AppletQ则用文本编辑器输入调用该Java Applet

的HTML 文档Q??.htm 为文件名后缀存盘?再执行命令行Q?br />
“appletviewer HTML文g名”来q行Java Applet。或用Netscape

打开该HTML文档?br />


 (tng) (tng) (tng) (tng)3. 关于本文中程序的说明



 (tng) (tng) (tng) (tng)Z(jin)使程序能够最z地体现其所代表的编E方法,本文中的E?br />
序一般采用最单的形式Q省略了(jin)U程{内宏V因此,本文的程序不

是“好”的E序Q但最Ҏ(gu)为初学者理解?br />
 (tng) (tng) (tng) (tng)本文的所有程序经~译后,生成的字节码文g?qing)对应的HTML文档

已上载到http://www.shu.edu.cn/~xyx/test/jvnetQ?均可正确

q行。连入Internet的读者可用浏览器打开该地址Q查看运行效果?br />
 (tng) (tng) (tng) (tng)q入Internet的读者也可以在本地硬盘输入ƈ~译本文的程序,

用Netscape的File/Open File菜单打开HTML文档Q体?x)编E方法ƈ

查看q行效果。如果读者想Java Applet 攑ֈ自己的主Z或其?br />
ftp服务器上Q在Netscape中用http协议或ftp协议调用Q出于安?br />
性限Ӟ应作如下修改Q?br />
 (tng) (tng) (tng)如果读者在某个WWWL上有帐号Q可以做个hHomepageQ一?br />
在用h目录创徏WWW或public_html目录卛_QHomepage的地址?br />
http://HostName/~个h帐号Q,可将本文E序中对应的

http://www.shu.edu.cn/~xyx/部分修改者自qWebl点地址Q?br />
然后编译后生成的字节码文g?qing)对应的HTML文档上蝲到自ql点上?br />
 (tng) (tng) (tng) (tng)如果读者的计算入了(jin)InternetQ也可以找一个可以上载的

ftpl点Q如Qftp://ftp.shnet.edu.cn/incomingQ将本文E序?br />
对应的http://www.shu.edu.cn/~xyx/部分修改为ftpl点的地址Q?br />
编译后生成的字节码文g?qing)对应的HTML文档上蝲到该l点上,以查

看运行效果?br />
 (tng) (tng) (tng) (tng)如果读者的计算机没有联|,也可以在单机上运行W(xu)eb 服务?br />
件如Webstar for Win95Q将本文E序中对应的http: //www. shu

.edu.cn/~xyx/部分修改为“http://本地IP地址”的形式Q来模拟

~程?br />


 (tng) (tng) (tng) (tng)二、Java
功能?qing)获?/font> 上资源的一般步?br />


 (tng) (tng) (tng) (tng)JavaE序可以获取
上结点的图象、声韟뀁HTML文档?qing)文?br />
{资源,q可以对获得的资源进行处理。例如JavaE序可以每隔一

定时间读取某l点提供的最新数据,q以图表的Ş式显C出来?br />
 (tng) (tng) (tng) (tng)在编E处理上Q一般先生成一个URLcd的对象,然后?Java

中相应的Ҏ(gu)QmethodQ获取该对象所代表的资源。下面分别介l?br />
Java
功能的几个例子,q由此介l几U不同的~程Ҏ(gu)?br />


 (tng) (tng) (tng) (tng)三、从
上获取图?br />


 (tng) (tng) (tng) (tng)Java Applet可以直接?/font>
上结点获取图象ƈ昄出来??br />
?jin)?jin)解其~程Ҏ(gu)和从本地昄图象的编E有何不同,我们先不考虑

功能Q来看一个简单的图象昄的例子:(x)



●程?

import java.applet.*;

import java.awt.*;

public class imag0 extends Applet{

 (tng) (tng)I(yng)mage image;

 (tng) (tng)public void init() {

image=getImage(getDocumentBase(),"test.gif");

 (tng) (tng)}

 (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng)g.drawImage(image, 0, 0,this);

 (tng) (tng)}

}



 (tng) (tng) (tng) (tng)q是一个最单的获取q显C图象的例子Q?在该例中Q?先用

getImage(getDocumentBase(),图象文g?从HTML文档所在位|调

用图象test.gifQƈ由此生成一个Imagecd的对象imageQ?然后?br />
drawImage(image, 0, 0,this)在屏q上图象显C出来?br />
 (tng) (tng) (tng) (tng)如果想从
上其他结点获取图象,关键是创建对应于 ?br />
其他l点的Imagecd的对象,一旦获得Imagecd的对象获得了(jin)Q?br />
便可以对其进行Q何可能的图象操作?br />
 (tng) (tng) (tng) (tng)Java提供?jin)如下方法可以创建对应于其他l点的图象:(x)

getImage(new URL(字符?)

 (tng) (tng) (tng) (tng)其用格式可有两U:(x)



 (tng) (tng) (tng) (tng)String (tng) (tng)url = "l点URL";

 (tng) (tng) (tng) (tng)I(yng)mage image;

 (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng)image = getImage(new URL(url));

 (tng) (tng) (tng) (tng)}

catch(Exception e){

System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng)}



?br />


URL imgur=null;

Image image;

try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)imgur=new URL("l点URL ");

 (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng)catch (MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng)image=getImage(imgur);



 (tng) (tng) (tng) (tng)前一U格式用“new URL(url)”生?URL 对象Q?q直接作?br />
getImage的参敎ͼ后一U格式先用“new URL(url)”生成一?URL

对象Q再传给getImage。两U格式本质上是一L(fng)。两U格式中Q?br />
生成URL对象的部分都包含?br />


try{

获取URL对象

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

catch (MalformedURLException e) {

出错提示

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

中?br />
 (tng) (tng) (tng) (tng)例如要调用http://www.shu.edu.cn/~xyx/img/shnet.jpgl点

的图象,W一U格式完整的E序如下Q?br />
●程?

import java.applet.*;

import java.net.*;

import java.awt.*;

public class imag extends Applet{

 (tng) (tng)I(yng)mage image;

 (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng)String (tng) (tng)url = "http://www.shu.edu.cn/~xyx/img/shnet.jpg";

 (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng)image = getImage(new URL(url));

 (tng) (tng) (tng) (tng)} catch(Exception e){}

 (tng) (tng)}



 (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng)g.drawImage(image, 0, 0,this);

 (tng) (tng)}

}



 (tng) (tng) (tng) (tng)W二U格式完整的E序如下Q?br />
●程?

import java.applet.*;

import java.net.*;

import java.awt.*;

public class imag2 extends Applet{

 (tng) (tng)I(yng)mage image;

 (tng) (tng)URL imgur=null;

 (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng)imgur=new URL("http://www.shu.edu.cn/~xyx/img/shnet.jpg");

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch (MalformedURLException e) {



 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)image=getImage(imgur);

 (tng) (tng)}

 (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng)g.drawImage(image, 0, 0,this);

 (tng) (tng)}

}



 (tng) (tng) (tng) (tng)上qC个程序分别以imag.java和imag2. java 存盘Q?执行

javac imag.java和javac imag2.javaQ将得到~译后生成的imag

.class和imag2.classQ最后创用这两个Java Applet的HTML?br />
档,如imag.class对应的HTML文档可如下:(x)

< html >

< head >

< title >Example < /title >

< /head >

< center >

< applet code=imag.class width=550 height=250 >

< /applet >

< /html >



 (tng) (tng) (tng) (tng)该HTML文档存入test.html文gQ用Netscape打开Q?如果?br />
的计机q入?jin)InternetQ便可以看到Java Applet 所昄的从|?br />
l上获得的图象了(jin)。(对于本文中其他不同的Java AppletQ?对应

的HTML文档只要修改其中相应的“code=imag.class”即可。)(j)



 (tng) (tng) (tng) (tng)四、从
上获取声?br />


 (tng) (tng) (tng) (tng)Java?/font>
上获取声x(chng)件ƈ播放声音的编E方法有两类Q一

是利用Java提供的play(URL)?qing)play(URL,String) 直接播放
上的声音文gQ另一cL通过getAudioClip(URL)或getAudioClip

(URL,String)先从
上获取声x(chng)Ӟq生成AudioClip cd?br />
对象Q然后对该对象进行操作?br />
 (tng) (tng) (tng) (tng)前者的使用格式是:(x)



String (tng) (tng)Audur = "l点URL";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng)play(new URL(Audur)); (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){}



?br />


String (tng) (tng)Audur = "l点URL";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)play(new URL(Audur),声音文g?;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){}

 (tng) (tng) (tng) (tng)后者用的格式是:(x)

String Audur = "l点URL";

AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)loopClip = getAudioClip(new URL(Audur));

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

catch(Exception e){

System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}



?br />


String Audur = "l点URL";

 (tng) (tng) (tng) (tng)AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)loopClip = getAudioClip(new URL(Audur) ,声音文g?;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

catch(Exception e){

System.out.println("Can't open the URL ");

}



 (tng) (tng) (tng) (tng)上面的四U格式都是将生成URL对象部分Q-“new URL(url)?br />
直接作ؓ(f)play或getAudioClip的参敎ͼ和前面处理图象的例子一P

也可以先用“new URL(url)”获取一个URL对象Q?再传l?play ?br />
getAudioClip。如对第一Uplay(URL)的格式, 也可采用如下的编

E格式:(x)

URL (tng) (tng)Audur =null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng)Audur=new URL("l点URL ");

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){

System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng)play(Audur);

 (tng) (tng) (tng) (tng)下面对前q四U从
上获取ƈ播放声音文g的格式各举一单的例子Q?br />
以作~程时参考:(x)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)●程? (tng) (tng) (tng)格式一

import java.applet.*;

import java.awt.*;

import java.net.*;

public class sound1 extends Applet



{ (tng) (tng) (tng)AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng)String (tng) (tng)Audur = "http://www.shu.edu.cn/~xyx/java/Animator/audio/bark.au";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng)play(new URL(Audur)); (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){}

 (tng) (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)●程? (tng) (tng) (tng)格式?br />
import java.applet.*;

import java.awt.*;

import java.net.*;

public class sound2 extends Applet

{ (tng) (tng) (tng)AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng) (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng) (tng)Audur = "http://www.shu.edu.cn/~xyx/java/Animator/audio/";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)play(new URL(Audur),"bark.au");

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){}

 (tng) (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)●程? (tng) (tng) (tng)格式?br />
import java.applet.*;

import java.awt.*;

import java.net.*;

public class sound extends Applet{

 (tng) (tng) (tng)AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng) (tng)String (tng) (tng)Audur = "http://www.shu.edu.cn/~xyx/java/Animator/audio/bark.au";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)loopClip = getAudioClip(new URL(Audur));

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} catch(Exception e){}

 (tng) (tng) (tng) (tng)}



 (tng) (tng) (tng)public void paint(Graphics g){

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)loopClip.loop();

 (tng) (tng) (tng)}

}



●程? (tng) (tng)格式?br />
import java.applet.*;

import java.awt.*;

import java.net.*;

public class sound0 extends Applet{

 (tng) (tng) (tng)AudioClip (tng) (tng)loopClip;

 (tng) (tng) (tng)URL auur;

 (tng) (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)auur=new URL("http://www.shu.edu.cn/~xyx/java/Animator/audio/");

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)catch (MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)loopClip = getAudioClip(auur,"bark.au");



 (tng) (tng) (tng) (tng)}



 (tng) (tng) (tng)public void paint(Graphics g){

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)loopClip.loop();

 (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng)五、显C?a class="wordstyle" target="_blank">|络上其他HTML文档



 (tng) (tng) (tng) (tng)利用Java提供的getAppletContext().showDocument(URL)可以

昄其他l点的HTML文档Q同前面的显C?a class="wordstyle" target="_blank">|络上其他结点的图象Q?br />
有两U格式,下面各D一例:(x)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)●程? (tng) (tng) (tng)格式一

import java.applet.*;

import java.awt.*;

import java.net.*;

public class showdoc extends Applet

{ (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng)URL docur= null;

 (tng) (tng) (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)docur=new URL("http://www.shu.edu.cn/~xyx/doc/manhua.html"); (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)catch (MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)if (docur != null) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)getAppletContext().showDocument(docur,"_blank");

 (tng) (tng) (tng) (tng) (tng) (tng)} (tng) (tng) (tng)

 (tng) (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)●程? 格式?br />
import java.applet.*;

import java.awt.*;

import java.net.*;

public class showdoc2 extends Applet

{ (tng) (tng) (tng) (tng)

 (tng) (tng) (tng)URL docur= null;

 (tng) (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng) (tng)try {

getAppletContext().showDocument(new URL("http://www.shu.edu.cn/

~xyx/doc/manhua.html")); (tng) (tng) (tng) (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng)catch (MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't open the URL ");

 (tng) (tng) (tng) (tng) (tng) (tng)} (tng) (tng) (tng)

 (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng) (tng)六、读?a class="wordstyle" target="_blank">|络上文件内?br />


 (tng) (tng) (tng) (tng) (tng)前述?a class="wordstyle" target="_blank">|络功能只是昄或播?a class="wordstyle" target="_blank">|络上结点的图象?声音?br />
HTML文档Qƈ没有对其内容q行处理。事实上QJavaq可d|络

上文件的内容Qƈ对其内容q行处理?br />
 (tng) (tng) (tng) (tng)d|络上文件内容的步骤可如下:(x)

 (tng) (tng) (tng) (tng)1. 创徏一个URLcd的对?br />
 (tng) (tng) (tng) (tng)如:(x)

 (tng) (tng) (tng) (tng)String url = "ftp://202.120.127.218/incoming/test/readtxt.html";

URL fileur;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

fileur = new URL(url); }

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch ( MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't get URL: " );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng)2. 利用URLcȝopenStream()Q获得对应的InputStreamcȝ对象

 (tng) (tng) (tng) (tng)如:(x)

InputStream filecon = fileur.openStream();

 (tng) (tng) (tng) (tng)3. InputStream对象转化为DataInputStreamcȝ对象

 (tng) (tng) (tng) (tng)如:(x)

 (tng) (tng) (tng) (tng)DataInputStream filedata = new DataInputStream(filecon);

 (tng) (tng) (tng) (tng)4. d内容

 (tng) (tng) (tng) (tng)如对前面的filedataQ可用filedata.readLine() 一行一行读

取内容,或用filedata.readchar一个字W一个字W读取内宏V??br />
d到的内容Q可由Java Appletq行各种处理Q?q将处理l果?br />
各种方式昄出来?br />
 (tng) (tng) (tng) (tng)下面的例子是d http://www.shu.edu.cn/~xyx/doc/manhua.html

文g内容的例子,为简zv见,该例中只文件的内容逐行dQ?br />
q在文本区显C出来?br />
●程?0

import java.io.*;

import java.net.*;

import java.awt.*;

import java.applet.*;

public class showfile extends Applet{

 (tng) (tng) (tng) (tng) (tng)URL fileur;

 (tng) (tng) (tng) (tng) (tng)TextArea showarea = new TextArea("Please wait a while for get

text",10,70);

 (tng) (tng) (tng) (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String url = "http://www.shu.edu.cn/~xyx/doc/manhua.html";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try { fileur = new URL(url); }

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch ( MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't get URL: " );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)add(showarea);

}



 (tng) (tng) (tng) (tng)public void paint(Graphics g) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nputStream filecon = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)DataInputStream filedata = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String fileline;

try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filecon = fileur.openStream();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filedata = new DataInputStream(filecon);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)while ((fileline = filedata.readLine()) != null) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)showarea.appendText(fileline+"\n");

}

}

catch (IOException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Error in I/O:" + e.getMessage());

}

 (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng)七、动态?a class="wordstyle" target="_blank">|络上资?br />
 (tng) (tng) (tng) (tng)在前面介l的例子的基上,可以动态地利用|络上的资源?br />
其方法是~制一个线E,每隔一定时间自动到相应l点d最新的

内容。本文对U程的编制不再展开Q读者可参考有x(chng)章或直接?br />
用下面的例子?br />
 (tng) (tng) (tng) (tng)例如对上例中dhttp://www.shu.edu.cn/~xyx/doc/manhua

.html文g内容的例子,加入U程后如下所C。该例子每隔5U更?br />
一ơ数据。如果http://www.shu.edu.cn/~xyx/doc/manhua.html?br />
存放的是一些变化较快的信息如股?jng)行情等Qƈ有程序随时动态地

更新其内容,则在Web中加入这UJava AppletQ可以让览者得?br />
动态的信息。进一步,也可以在E序中对数据q行处理Qƈ用图?br />
方式昄处理l果。例如将各时ȝ数据l制成曲U,览者可?br />
看到动态变化的曲线?br />
//E序11

import java.io.*;

import java.net.*;

import java.awt.*;

import java.applet.*;

public class dynashow extends java.applet.Applet

 (tng) (tng) (tng) (tng)implements Runnable {

 (tng) (tng) (tng) (tng)Thread dthread;

 (tng) (tng) (tng) (tng)URL fileur;

TextArea showarea = new TextArea("Wait for a while...",10,70);

 (tng) (tng) (tng) (tng) (tng)public void init() {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String url = " http://www.shu.edu.cn/~xyx/doc/manhua.html ";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try { fileur = new URL(url); }

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch ( MalformedURLException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Can't get URL: " );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)add(showarea);

 (tng) (tng) (tng) (tng) (tng)}



 (tng) (tng) (tng) (tng) (tng)public void start() {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (dthread == null)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng){

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dthread = new Thread(this);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dthread.start();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng)public void stop() {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (dthread != null) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dthread.stop();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dthread = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng)}



 (tng) (tng) (tng) (tng)public void run() {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nputStream filecon = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)DataInputStream filedata = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String fileline;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)while(true){

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filecon = fileur.openStream();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filedata = new DataInputStream(filecon);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)while ((fileline = filedata.readLine()) != null) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)showarea.appendText(fileline+"\n");

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch (IOException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Error in I/O:" + e.getMessage());

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try{

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)dthread.sleep(5000);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)catch (InterruptedException e){}

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)repaint();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng)}

 (tng) (tng) (tng) (tng) (tng)}

}



 (tng) (tng) (tng) (tng)八、Java|络能力的限?br />


 (tng) (tng) (tng) (tng)Z安全性考虑Q在用netscape览ӞJava Applet 只能?br />
其所在的L建立q接Q因此,前面的程序编译后大部分只能存?br />
在http://www.shu.edu.cn/~xyx对应的主Z。存攑ֈ其他L?br />
需更改E序中的l点地址。否则浏览器显C安全出错?br />
 (tng) (tng) (tng) (tng)但对昄|络上其他HTML文档没有此限Ӟ如程??Q,?br />
者可以将E序~译后放CQ意WWW服务器或FTP服务器,均可正常q?br />
行?br />
 (tng) (tng) (tng) (tng)此外Q当览器从本地盘打开调用Java Applet的HTML文档Ӟ

也不受此限制。因此,本文所有的E序都可存放在本地盘~译Q只

要用netscape的File/Open File菜单打开Q便可正运行?br />
 (tng) (tng) (tng) (tng)对于另一UJavaE序Q-Java ApplicationQ也无此限制Q例

如对于读?a class="wordstyle" target="_blank">|络上文件内容的E序10Q对应的Java Application?br />
作如下编E:(x)



●程?1

import java.io.*;

import java.net.*;

import java.awt.*;

class showfile2 {

 (tng) (tng) (tng) (tng) (tng)public static void main(String args[]){

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)I(yng)nputStream filecon = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)DataInputStream filedata = null;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String fileline;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String url = "http://www.shu.edu.cn/~xyx/doc/manhua.html";

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)URL fileur;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try {

 (tng) (tng) (tng)fileur = new URL(url);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filecon = fileur.openStream();

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)filedata = new DataInputStream(filecon);

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)while ((fileline = filedata.readLine()) != null) {

System.out.println(fileline+"\n");

}

}

catch (IOException e) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Error in I/O:" + e.getMessage());

}

 (tng) (tng)}

}

 (tng) (tng) (tng) (tng)其以showfile2.java存盘Q用javac showfile2.java~译后,

只需执行“java showfile2”便可以在屏q上打印?br />
http://www.shu.edu.cn/~xyx/doc/manhua.html 文g的内宏V?br />


 (tng) (tng) (tng) (tng)?ji)、创建URL对象的方?br />


 (tng) (tng) (tng) (tng)在前面的例子中我们统一使用new URL(url字符?的Ş式创?br />
URL对象。其实,Java提供?jin)四U创建URL对象的Ş式:(x)

 (tng) (tng) (tng) (tng)1.new URL(url字符? (tng) (tng) (tng) (tng)本文中的E序均采用此U格式,如:(x)

new (tng) (tng)URL("http://www.shu.edu.cn/~xyx/doc/manhua.html")

 (tng) (tng) (tng) (tng)2.new URL(协议Q主机名Q文件名或\? (tng) (tng) (tng) (tng)如程?中的

String (tng) (tng)url = "http://www.shu.edu.cn/~xyx/img/shnet.jpg";

image = getImage(new URL(url));部分可改为:(x)

image = getImage(new URL("http","www.shu.edu.cn","/~xyx /img/shnet.jpg"));

 (tng) (tng) (tng) (tng)3.new URL(协议Q主机名Q端口号Q文件名或\?1

如:(x)new URL("http","www.shu.edu.cn",80, "/~xyx/doc/manhua.html")

 (tng) (tng) (tng) (tng)4.new URL(基准urlQ文件名或\?



 (tng) (tng) (tng) (tng)十、实?a class="wordstyle" target="_blank">|络功能的其他方?br />


 (tng) (tng) (tng) (tng)以上着重介l了(jin)利用Java的URLcdC|络上获取声韟??br />
象、HTML文档?qing)文件数据的~程Ҏ(gu)。Java?a class="wordstyle" target="_blank">|络功能很强大,?br />
上面介绍的外Q还可以利用URLconnection cd现更q泛?a class="wordstyle" target="_blank">|络?br />
能,如向WWW 服务器上?CGI E序发送信息等Q?通过 Socket ?br />
ServerSocketc,可以自己~写客户软g?qing)服务YӞq可以自?br />
设计通讯协议?br />


〖参考文献?br />
Laura Lemay,Charles L. Perkins (tng) (tng)"Teach Yourself JAVA in 21 Days"

摘自《Internet世界?


zjw_albert 2006-03-20 12:28 发表评论
]]>
Java入门W记_SocketQ{载)(j)http://www.tkk7.com/zjw-albert/archive/2006/03/20/36281.htmlzjw_albertzjw_albertMon, 20 Mar 2006 04:21:00 GMThttp://www.tkk7.com/zjw-albert/archive/2006/03/20/36281.htmlhttp://www.tkk7.com/zjw-albert/comments/36281.htmlhttp://www.tkk7.com/zjw-albert/archive/2006/03/20/36281.html#Feedback0http://www.tkk7.com/zjw-albert/comments/commentRss/36281.htmlhttp://www.tkk7.com/zjw-albert/services/trackbacks/36281.html1. Client/Server Networking
Java通过socket来完成它所有的
底层的通讯Qsocket是一U通讯的通道Q通过它可以将数据通过特定的端中发送及(qing)接收。Java中的socket可以分成二大c:(x)

Q?Q?Datagram SocketsQ数据包socketQ?br />
Q?Q?Stream SocketsQ流socketQ?br />
1.2 Datagram Socket
Datagram socket使用UDP来实现数据通讯Q因此它不能保证数据能够到达目的圎ͼ但是׃它不需要专用的
链接Q所以它所需的资源相对少的多?br />
Datagram以包的方式发送数据,但它不能保证q些数据包以特定的顺序到辄的,因此包中往往需要包含序列号的信息,接收方可以根据序列号的信息决定是否所有的包都已收刎ͼq按正常序重组q些包?br />
Java通过两个cDatagramSocket和DatagramPacket来支持Datagram socket。DatagramSocket实现?jin)Datagram socket的基本功能,而DatagramPacket则提供了(jin)对包的一些支持?br />
DatagramSocket的几个重要方法:(x)

Q?Q?DatagramSocket()Q随机绑定一个有效的端口Q?br />
Q?Q?DatagramSocket(int port)Q绑定指定的端口Q?br />
Q?Q?Void send(DatagramPacket p)Q发送数据报Q由于目的地的地址信息已包含在数据报中Q所以不需要在本函C提供地址信息Q?br />
Q?Q?synchronized void receive(DatagramPacket p)Q接收数据包Q线E安全;

Q?Q?synchronized void close()Q关闭socketQ?br />
在DatagramSocket中ƈ不区分ServerSocket和ClientSocketQ如果一定要区分Q那么发送的是clientQ而接收的是server?br />
DatagramPacket有以几个重要的方法:(x)

Q?Q?DatagramPacket(byte ibuf[], int ilength)Q用于接收数据报Q?br />
Q?Q?DatagramPacket(byte ibuf[], int ilength, InetAddressiaddr, int iport)Q用于发送的数据报;

Q?Q?byte[] getData()

Q?Q?int getLength()

以下是完整的Datagram Socket的例子:(x)

接收端,Server端代码:(x)

import java.io.*;

import java.net.*;



class FortuneServer1 extends Thread

{

DatagramSocket ServerSocket;

public FortuneServer1()

{

super("FortuneServer1");

try

{

ServerSocket = new DatagramSocket(1114);

System.out.println("FortuneServer up and running...");

}

catch (SocketException e)

{

System.err.println("Exception: couldn't create datagram socket");

System.exit(1);

} }



public static void main(String[] args)

{

FortuneServer1 server = new FortuneServer1();

server.start();

}



public void run()

{

if (ServerSocket == null)

return;



while (true)

{

try

{

InetAddress address;

int port;

DatagramPacket packet;

byte[] data = new byte[256];

int num = 1;



packet = new DatagramPacket(data, data.length);

ServerSocket.receive(packet);

address = packet.getAddress();

port = packet.getPort();



File inFile = new File("Fortunes.txt");

FileInputStream inStream = new FileInputStream(inFile);



if (inStream.read(data) <= 0)

{

System.err.println("Error: couldn't read fortunes");

}



packet = new DatagramPacket(data, data.length, address, port);

ServerSocket.send(packet);

}

catch (Exception e)

{

System.err.println("Exception: " + e);

e.printStackTrace();

} } } }

说明Q?br />
Q?Q?q个例子中接收端的socket使用?jin)多U程Q多U程的概念可以参考本文的多线E部分;

Q?Q?在构造函C创徏?jin)DatagramSocketQƈ且用了(jin)1114q个端口Q?br />
Q?Q?本例子的关键函数是runQ它使用?jin)死循环Q在循环中用了(jin)receiveq方法来临听1114端口Q如?114端口没有h数据到来Q那么这个程序就一直停留在receiveq个位置Q不再往下执行;

Q?Q??114端有数据ӞreceiveҎ(gu)接收到的DatagramPacket数据包放在packetq个对象中,然后解析其中的数据,获取发送方的地址信息Q?br />
Q?Q?然后再创建DatagramPacket包,q填充数据,发送到原接收端?br />
以下是发送端的代码:(x)

import java.io.*;

import java.net.*;

class FortuneClient

{

public static void main(String args[])

{

FortuneClient client = new FortuneClient();

System.out.println(client.getMessage());

}



public String getMessage()

{

String fortune;

try {

DatagramSocket socket;

DatagramPacket packet;

byte[] data = new byte[256];



socket = new DatagramSocket();

packet = new DatagramPacket(data, data.length,InetAddress.getByName("127.0.0.1"), 1114);

socket.send(packet);



packet = new DatagramPacket(data, data.length);

socket.receive(packet);

fortune = new String(packet.getData(), 0);

socket.close();

}

catch (UnknownHostException e) {

System.err.println("Exception: host could not be found");

return null;

}

catch (Exception e) {

System.err.println("Exception: " + e);

e.printStackTrace();

return null;

}

return fortune;

} }

客户端的代码与服务器端的代码基本相同Q只是没有了(jin)循环Qƈ且处理步骤与服务器端的基本相反。这也说明了(jin)Datagram Socket不真正区分Server和Client?br />
1.3 Stream Socket
Stream Socket与Datagram Socket不同Q它有一个永久性的链接Q可以确保数据可靠的发送到Ҏ(gu)。但是Stream Socket所占的资源更多?br />
Java主要通过Socket?qing)ServerSocket来实现Stream SocketQ一个用于客L(fng)Q另一个用h务器端?br />
Socketcȝ几个重要Ҏ(gu)如下Q?br />
Q?Q?Socket(String host, int port)

Q?Q?Socket(InetAddress address, int port)

Q?Q?synchronized void close()

Q?Q?InputStream getInputStream()

Q?Q?OutputStream getOutputStream()

可以看出Stream Socket中的Socket与Datagram Socket中的Socket的区别:(x)

Q?Q?在构造函CQ这里需要指定服务器的地址与端口,用于它发送数据之前徏立链接,而Datagram的Socket不需要徏立链接,它仅需要在要发送的数据包中包含地址信息卛_Q?br />
Q?Q?Stream Socket的两个重要方法和其它的Ҏ(gu)cMQ而且在操作上也相|其实在操作Stream SocketӞ只要建立?jin)链接,那么以后的操作和的操作一样了(jin)Q你可以忘(sh)(jin)你在操作SocketQ只当做自己在操作普通的?br />
ServerSocket有以下几个重要的Ҏ(gu)Q?br />
Q?Q?ServerSocket(int port)Q监听指定端口,监听旉为默认?0Q?br />
Q?Q?ServerSocket(int port, int count)Q监听指定端口,q指定监听时_(d)

Q?Q?ServerSocket(int port, int backlog, InetAddress bindAddr)Q只接收指定接口发过来的数据Q?br />
Q?Q?Socket accept()QaccpetҎ(gu)?x)返回一个Socket对象Q用该Socket对象的getInputStream?qing)getOutputStreamҎ(gu)获取输入?qing)输出流。由此可见无论是服务器端q是客户端,它们都是通过Socket对象来收发数据的。程序执行到accpet时会(x)q入监听状态,不再向下执行一直到接收到数据?br />
Q?Q?void close()

以下是关于Stream Socket的一个例子,在这个例子中使用单独的二个类Receiver和Sender负责Ҏ(gu)定的输入?qing)输出流q行操作Q用另一个类SocketPerformer来创建Receiver和Senderq两个类的实例,q传入指定的输入?qing)输出流Q而在Client?qing)Serverq两个类中,负责创徏SocketPerformer对象Qƈ传入指定的Socket。因此这五个cd功能上分Z层,W一层负责对进行操作,W二层负责创建指定的Socket,q这些Socket传到第一层,W三层负责创建Socketq将q些Socket传到W二层?br />
Receriver代码Q?br />
package socketChat;

import java.io.BufferedReader;

public class Receiver extends Thread {

BufferedReader reader;

public Receiver(BufferedReader theSocketReader) {

reader = theSocketReader;

}



public void run() {

while (true) {

try {

String words = reader.readLine(); System.out.println("\r\n<<< " + words);

} catch (Exception e) {

e.printStackTrace();

return;

} } }}

Sender代码Q?br />
package socketChat;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.PrintWriter;



public class Sender extends Thread {

PrintWriter writer;

public Sender(PrintWriter theWriter) {

writer = theWriter;

}

public void run() {

try {

while (true) {

BufferedReader consoleReader = new BufferedReader(

new InputStreamReader(System.in));

String userInput = consoleReader.readLine();

writer.write(userInput + "\r\n");

writer.flush(); // send the data in buffer immediately

}

} catch (Exception e) {

e.printStackTrace();

return;

} }}

SocketPerformer代码Q?br />
package socketChat;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

public class SocketPerformer {

Socket socket;

public SocketPerformer(Socket theSoc){

socket = theSoc;

}

public void execut() throws Exception{

BufferedReader socketReader = new BufferedReader(new InputStreamReader(

socket.getInputStream()));

PrintWriter socketWriter = new PrintWriter(socket.getOutputStream());

System.out.println("connection built !");



Receiver rec = new Receiver(socketReader);

rec.start();



Sender sender = new Sender(socketWriter);

sender.start();

}}

Server代码Q?br />
package socketChat;



import java.net.ServerSocket;

import java.net.Socket;

public class Server {

public static void main(String[] args) throws Exception {

ServerSocket server = new ServerSocket(30000, 5);

Socket socket = null;

System.out.println("waiting incoming connection...");

socket = server.accept();

System.out.println("a connection built!");

System.out.println("the peer ip is: " + socket.getInetAddress().getHostAddress());

new SocketPerformer(socket).execut();

server.close();

}}

Client端代码如下:(x)

package socketChat;

import java.net.Socket;

public class Client {



public static void main(String[] args) throws Exception {

String ip = "127.0.0.1";

int port = 30000;

System.out.println("connecting to server: " + ip

+ " at port: " + port + " ...");



Socket soc = new Socket(ip, port);

new SocketPerformer(soc).execut();

}}

2. 其它
Q?Q?帔R定义以final做修饰符Q如final int I = 3Qfinalq可以用在class?qing)method上,如果用在class上,那么该class不能被承,如果用在method上,那么该method不能被重?br />
Q?Q?cd量定义:(x)static int sum

Q?Q?判断对象cdQobjName instanceof classNameQ如"helloWorld" instanceof StringQ判断的l果是true

Q?Q?提取对象的类名:(x)objName.getClass().getName()

Q?Q?java.langQJava最基本的包Q包含java语言最基本的定?br />
Q?Q?java.utilQ包含如DateQ及(qing)基本的集合类Q如Vector、Hashtable{?br />
Q?Q?java.ioQ包含输入输出的定义

Q?Q?java.netQ包含如Socket{?br />
Q?Q?java.awtQ用于Window界面开?br />
Q?0Q?java.appletQ用于applet开?br />
Q?1Q?null关键字引用null对象Q注意大写

Q?2Q?每个基本的数据类型如intQ都有相应的cM之对应中Int

Q?3Q?构造函数名与类名相同,q且不需要返回类型,卛_构造函数前不需要加cd修饰W?br />
Q?4Q?调用自n的构造函敎ͼ(x)this(参数列表);

Q?5Q?调用父类的构造函敎ͼ(x)super(参数列表);

Q?6Q?调用父类已被重蝲的函敎ͼ(x)super.Ҏ(gu)?参数列表);

Q?7Q?在同一文g中可以有多个cȝ定义Q但只能有一个类是publicq且cd与文件一P该文件编译成功后?x)生成多?class文gQ与cȝ定义一一对应Q?br />
Q?8Q?接口比抽象类功能强有Q抽象类属于特定的类l构?wi)中Q它不能被其它树(wi)中的cd享;

Q?9Q?接口的定义与cȝ定义cMQ只需classҎ(gu)interface卛_Q但接口定义必须是public或者缺省的QpackageQ;

Q?0Q?在接口中可以定义Ҏ(gu)和变量,接口中的定义的方法应是publicq且是abstract的(~省Q;变量的定义必Lpublic static finalQ缺省)(j)Q?br />
Q?1Q?String.copyValueOf(buffer, 0, offset)Q用于从字符数组中取出字W,qŞ成字W串Q?br />
Q?2Q?new String(buf, 0, count)

Q?3Q?System.in(标准输入)是一个InputStreamQ?br />
Q?4Q?System.err是一个PrintStreamQ?br />
Q?5Q?System.out是一个PrintStreamQ?/font>


zjw_albert 2006-03-20 12:21 发表评论
]]>
վ֩ģ壺 ƷŮͬһվ| 99þۺϾƷ| 鶹91Ƶ| Ʒѹۿһ| һɫþ88ۺ޾Ʒ | ŷպëƬ߿վ| þҹɫƷav| ˳վ| С˵ۺͼ| רר| Ƶһ| պƷƵ߹ۿ | ѹۿ| ޾ƷĻ| պѾƷƵ| Ʒ޾Ʒ| èwww˳| ۺɫһ| Ʒһѿ| ޾Ʒavɫ| ѹۿһëƬa | պ޹Ƶ| ˳վ18ֹþӰԺ| ߹ۿվ| 츾AVһ˳| ѿٸƵ| ͵͵޸| JIZZJIZZйٸ| ִˬƵ| ޾ƷҹҹҹŮ| ɫ鶹һƷһAVһ| ޾Ʒ**ëƬ| ˬˬˬƵ| ձŷɫƵ߲| ŮͬAƬ߹ۿ| aaѹۿ| ˳ɵӰ| Hվ߹ۿ| AVһ| ޾ƷԲ߹ۿ| ĻѿӰ|