﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-amp@java-随笔分类-Java common</title><link>http://www.blogjava.net/amplifier/category/7854.html</link><description>amplifier's java blog
&lt;br&gt;
&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "ca-pub-5575070670019942";
/* blogjava */
google_ad_slot = "7055672771";
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;</description><language>zh-cn</language><lastBuildDate>Fri, 17 Nov 2017 07:37:54 GMT</lastBuildDate><pubDate>Fri, 17 Nov 2017 07:37:54 GMT</pubDate><ttl>60</ttl><item><title>利用jmtp库读取手机文件</title><link>http://www.blogjava.net/amplifier/archive/2017/11/17/432903.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Fri, 17 Nov 2017 06:54:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2017/11/17/432903.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/432903.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2017/11/17/432903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/432903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/432903.html</trackback:ping><description><![CDATA[&nbsp;每次换手机，把旧手机的数据迁移到新手机就是个很麻烦的事情，幸好最近华为的&#8220;手机克隆&#8221;APP越来越强大，居然能够把微信的聊天记录包括图片原封不动地迁移到新手机上，以前用微信自带的聊天记录转移功能只能转移文字信息，图片视频全部丢失，不知道现在的怎么样。手机克隆还能把SD卡的内容也转移过来，基本满足了需要。<br />
但是要把手机上的东西传到电脑就没那么简单了，现在已经没有了以前的大容量存储模式，只能选择MTP模式，这种模式其实不是一个完整的文件系统，有很多限制，所以一些传统的软件读取不到，例如FastCopy是用不了的，用Windows自带的文件管理器来复制，开始计算时间就要等很久，中间出了个错就前功尽弃；还有通过手机上的APP访问电脑共享的方式，在手机上复制也可以，但是同样会莫名其妙卡死，FTP同理，折腾了好久，还是觉得自己动手比较好。<br />
MTP协议在维基百科里解释得比较清楚：<a href="https://en.wikipedia.org/wiki/Media_Transfer_Protocol">https://en.wikipedia.org/wiki/Media_Transfer_Protocol</a> ，简单点说就是：<br />
1、不是以块设备的形式访问，跟U盘不同；<br />
2、只能单线程访问，不能同时进行多个操作，只能一个接一个；<br />
3、控制权在设备上，对外展示的内容由设备决定；<br />
4、默认不能直接对文件进行部分修改，只能复制过来修改完再复制回去，但Android对协议做了扩展，能够修改部分文件内容；<br />
5、在Linux上有些软件能够把它挂载为文件系统，这样其他软件就能像访问普通文件系统一样访问了，但是Windows下似乎没有。<br />
<br />
不过有人开发了一个在Windows下通过JNI实现的Java库jmtp，项目托管在Google Code，被墙了，但是GitHub有人fork了一个，可以下载下来，我下载的是<a href="https://github.com/reindahl/jmtp">https://github.com/reindahl/jmtp</a><br />
里面包含了C++的代码和Java的代码，以及两个已经编译好的dll文件，分别用于Win32和Win64，把其中一个dll文件放在工程目录下，再把Java源代码加入工程中即可使用，文档比较简陋，但是看test目录下的MtpTest.java，基本可以摸到如何使用了，这个协议比较简单，其实没什么功能，我要的只是把文件复制到电脑上。<br />
根据MtpTest.java，稍微修改一下，做个递归复制即可把手机上的所有文件复制到电脑上：<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;test;<br />
<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.File;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.FileWriter;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.io.IOException;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.math.BigInteger;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.nio.file.Files;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.nio.file.Path;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.nio.file.Paths;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.rmi.server.SocketSecurityException;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;java.util.ArrayList;<br />
<br />
<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;jmtp.PortableDevice;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;jmtp.PortableDeviceFolderObject;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;jmtp.PortableDeviceManager;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;jmtp.PortableDeviceObject;<br />
</span><span style="color: #0000FF; ">import</span><span style="color: #000000; ">&nbsp;jmtp.PortableDeviceStorageObject;<br />
<br />
<br />
</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;TestApp&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">PortableDeviceStorageObject</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;devices&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ArrayList</span><span style="color: #000000; ">&lt;&gt;</span><span style="color: #000000; ">();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PortableDeviceManager&nbsp;manager&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;PortableDeviceManager();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(PortableDevice&nbsp;device&nbsp;:&nbsp;manager)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(device);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;device.open();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Iterate&nbsp;over&nbsp;deviceObjects</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(PortableDeviceObject&nbsp;object&nbsp;:&nbsp;device.getRootObjects())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;storageName</span><span style="color: #000000; ">=</span><span style="color: #000000; ">object.getName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(storageName);<br />
</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;If&nbsp;the&nbsp;object&nbsp;is&nbsp;a&nbsp;storage&nbsp;object</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(object&nbsp;</span><span style="color: #0000FF; ">instanceof</span><span style="color: #000000; ">&nbsp;PortableDeviceStorageObject)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PortableDeviceStorageObject&nbsp;storage&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(PortableDeviceStorageObject)&nbsp;object;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(storage.getChildObjects().length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(PortableDeviceObject&nbsp;child&nbsp;:&nbsp;storage.getChildObjects())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copyall(child,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">E:\\手机备份\\</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">object.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;device.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;</span><span style="color: #000000; ">&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;copyall(PortableDeviceObject&nbsp;obj,String&nbsp;path)&nbsp;{<br />
</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(obj&nbsp;</span><span style="color: #0000FF; ">instanceof</span><span style="color: #000000; ">&nbsp;PortableDeviceFolderObject)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;objName</span><span style="color: #000000; ">=</span><span style="color: #000000; ">obj.getName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(objName.contains(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objName</span><span style="color: #000000; ">=</span><span style="color: #000000; ">objName.replace(</span><span style="color: #000000; ">'</span><span style="color: #000000; ">:</span><span style="color: #000000; ">'</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">：</span><span style="color: #000000; ">'</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;newPath&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;path</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">\\</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">objName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">创建文件夹：</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">newPath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008000; "></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span> File&nbsp;file&nbsp;=&nbsp;new&nbsp;File(newPath);<br />
</span><span style="color: #008000; "></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!file.exists())&nbsp;{<br />
</span><span style="color: #008000; "></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file.mkdirs();<br />
</span><span style="color: #008000; "></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(PortableDeviceObject&nbsp;subObj:((PortableDeviceFolderObject)&nbsp;obj).getChildObjects())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copyall(subObj,newPath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(obj.getName().contains(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">开始复制文件到：</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">path</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">\\</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">obj.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;file&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;File(path);<br />
</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #008000; "></span><span>obj.copy(file.toPath());</span><span style="color: #008000; "></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">文件复制完成！</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #000000; "><br />
}</span></div>
其中发现有点问题：<br />1、Android设备文件名里是可以包含冒号（:）的，但Windows是不可以的，所以复制到这些文件的时候会有问题，于是遇到目录名这样就把它改为中文的冒号（：），但是遇到文件名这样就不行了，因为这个库的copy函数只需要指定目标目录，不需要指定目标文件名，所以这些文件只能放弃；<br />2、Android手机的MTP协议是由&#8220;媒体存储&#8221;这个系统APP控制的，有时候手机上可以看到的文件，通过MTP访问却怎么也看不到，重启手机也不行，应该就是这个APP没有更新数据，需要把它的系统数据清除掉，等它重建完重新访问就可以看到了，不过这个重建时间非常长，可以查看它数据占用的空间，刚清除之后会发现它占用的空间会不断增长，到了不增长的时候就是重建完了，就可以正常访问了；<br />3、这个库有时候还有点bug，有一次发现它读取到的文件和文件夹都没有了最后一个.后面的部分，所以总是卡住，重新插拔一下手机数据线又没问题了；<br />4、为了避免复制了半天结果发现不完整，又要重来，最好在复制前先统计一下文件大小，看看跟手机上看到的占用存储空间是不是一致，对于MTP设备上的文件，可以通过getSize函数得到大小，把上面复制操作改为大小累加即可，速度比复制快一些，不过由于小文件太多，也不会快很多。<br /><br />把手机里的文件复制到电脑后，通过一些简单的分析，发现有很多其实是垃圾来的，也可以为手机空间清理提供参考，因为在电脑上分析起来比在手机上方便一些。例如一些视频APP的缓存，居然超过1G，占用了宝贵的内部存储空间，之前一直都没发现，通过电脑里的按文件大小搜索才发现。<img src ="http://www.blogjava.net/amplifier/aggbug/432903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2017-11-17 14:54 <a href="http://www.blogjava.net/amplifier/archive/2017/11/17/432903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用httpclient和正则表达式完成一些无聊的重复性任务</title><link>http://www.blogjava.net/amplifier/archive/2016/01/12/429014.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 12 Jan 2016 07:54:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2016/01/12/429014.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/429014.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2016/01/12/429014.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/429014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/429014.html</trackback:ping><description><![CDATA[最近新部署了一个信息系统，厂家居然没有升级方案，所有数据都要重新输入，包括用户、角色等都要重新配置，真是操蛋。要是一个个录入简直是日狗了，这些用户在其他信息系统早已存在，但是每个都复制粘贴提交一遍也不是办法，于是就想用程序自动完成这些操作。步骤如下：<br />1、从其他信息系统的数据库导出用户信息，也可以直接从其他信息系统的界面把所有用户信息复制下来放在一个文本文件里，反正就是准备好数据源；<br />2、在需要录入用户信息的系统中，用人工操作的方式登录系统，并录入一个用户，同时用Wireshark抓包，查看整个过程要提交一些什么样的表单数据；<br />3、在程序中用httpclient提交同样的数据，完成登录，并从第1步的数据源中读取用户信息，然后循环提交录入用户所需的数据，完成用户的录入；<br />4、新系统没有默认的用户角色，是需要一个个修改的，是根据用户的ID来确定当前修改的用户，并且提交一个角色ID来进行设定，因此需要首先获取用户的ID，然后根据该ID来提交角色ID，而用户ID是通过用户列表页面获取到的，因此还需要通过正则表达式来获取所有用户的ID，然后循环提交角色ID，完成角色设定。<br /><br />花了不少时间才搞定，有几个地方需要注意：<br />1、如果表单数据不包含中文，直接把表单的Name和Value加在HttpPost的URL的?后面即可，不需要专门建立NameValuePair，如下所示：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">HttpPost&nbsp;httppost&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;HttpPost(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">http://1.1.1.1/test/adduser?userid=abc&amp;username=efg</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />httpclient.execute(httppost);</span></div><br />但是，如果表单数据包含中文，例如姓名，用这种方式提交的表单数据会出现乱码，即使通过URLEncoder进行编码后再发也不行，必须建立NameValuePair，再加到HttpPost的Entity里面，如下所示：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">HttpPost&nbsp;httppost&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;HttpPost(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">http://1.1.1.1/test/adduser?userid=abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />List</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">NameValuePair</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;nvps&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ArrayList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">NameValuePair</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">();<br />nvps.add(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;BasicNameValuePair(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">username</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">张三</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />httppost.setEntity(</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;UrlEncodedFormEntity(nvps,&nbsp;HTTP.UTF_8));<br />httpclient.execute(httppost);</span></div><br />2、用于网页内容查找的正则表达式的使用方式一般为：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Pattern&nbsp;p&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Pattern.compile(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">.*?abc(whattoget)123.*?");</span><span style="color: #000000; "><br /></span><span style="color: #000000; ">Matcher&nbsp;m&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;p.matcher(line);<br /></span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(m.matches()){<br />&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;whattoget&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;m.group(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />}</span></div><div><span style="color: #000000; "></span><div><span style="color: #000000; ">"</span><span style="color: #000000; ">.*?abc(whattoget)123.*?"</span><span style="color: #000000; ">就是一个正则表达式，如果用于匹配一行的时候，由于要查找的内容是在行中间，所以前后需要加上.*?，表示前后可以是任意字符，也可以什么都没有，而表达式中间的(whattoget)就表示一个group，编号为1，编号为0的group是整个匹配的字符串，找到之后提取group(1)即可得到想要的内容。<br />测试正则表达式是一项很麻烦的工作，不过有个很好的软件可以完成此工作：RegexBuddy，支持各种语言的正则表达式的调试。<br />学习正则表达式的宝典是《Mastering Regular Expression》。<br /></span></div></div><img src ="http://www.blogjava.net/amplifier/aggbug/429014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2016-01-12 15:54 <a href="http://www.blogjava.net/amplifier/archive/2016/01/12/429014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何让线程暂停，又能随时唤醒？</title><link>http://www.blogjava.net/amplifier/archive/2015/03/10/423348.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 10 Mar 2015 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2015/03/10/423348.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/423348.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2015/03/10/423348.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/423348.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/423348.html</trackback:ping><description><![CDATA[做GUI程序的时候，通常有个后台工作线程在努力工作，但是中间又需要一些暂停，而关闭程序的时候，必须立即结束那个线程，退出程序，也有的时候需要停止后台线程，但不关闭程序。例如，做一个目录监控程序，发现目录中有文件的时候，执行一定的操作，执行完之后没有文件了，就要暂停一下，过几秒或几分钟再次检测，这时候就要对线程进行暂停操作，如果在暂停的时候，用户要关闭程序，就必须马上停止线程，如果用户需要暂停检测，按下某个按钮后，需要让线程马上停止，但再次按下某个按钮，线程又必须马上开始。<br />
<br />
以前我都是通过检测停止标记和用Thread.sleep(time)来完成的，后台线程的每次循环都要检查停止标记，如果发现停止标记已设定，就不再循环，退出线程，在线程内部，如果需要暂停，就执行Thread.sleep(time)。通过把线程的setDaemon(true)方法，还可以让线程作为后台线程，当图形界面关闭后，线程也自动退出。<br />
<br />
但是，这种方式有个问题，如果我需要在图形界面上点击按钮来停止线程，但并不退出程序，而点击按钮的时候线程正处于sleep状态，就对它没有任何办法，只能让它醒过来再操作，如果sleep的时间比较长，例如1分钟，那么点击按钮之后，用户最多要等1分钟才能把线程停下来。<span style="text-decoration: line-through;">当然，Thread对象有个interrupt方法，但是已经被标记为过期，一般不建议使用了。</span><span style="color: red;">感谢评论中</span><a style="color: red;" id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://watchzerg.github.io" target="_blank">watchzerg</a><span style="color: red;"></span><span style="color: red;">的提醒，Thread的interrupt()并没有标记为过期，可以按照他的说法来操作，更为简单。</span><br style="color: red;" />
<br />
怎么让线程能暂停，又能随时叫醒呢？原来Java里最原始的对象Object就自带此功能。<br />
<br />
每个Object都有wait(time)和notify()方法，前者就是让拥有该Obejct的线程处于暂停状态，后者则让线程马上唤醒，通过这两个方法，就能够满足上述的所有要求。<br />
<br />
首先，建立一个同步对象：<br />
Object syncObj = new Object();<br />
<br />
然后在线程中需要暂停的地方，调用该对象的wait(time)方法：<br />
<div>synchronized (syncObj) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; syncObj.wait(60*1000);<br />
}<br />
<br />
在图形界面的按钮监听事件中，对该对象执行notify()方法：<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; button_1.addSelectionListener(new SelectionAdapter() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;@Override<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public void widgetSelected(SelectionEvent e) {<br />
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; thread.setStop(true);
<div>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; synchronized (syncObj) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; syncObj.notify();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; //为了等待线程退出，还可以加上以下语句：<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; thread.join();</div>
<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;});<br />
<br />
</div><img src ="http://www.blogjava.net/amplifier/aggbug/423348.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2015-03-10 16:52 <a href="http://www.blogjava.net/amplifier/archive/2015/03/10/423348.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse导出的可执行JAR文件启动非常慢</title><link>http://www.blogjava.net/amplifier/archive/2015/03/10/423344.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 10 Mar 2015 07:07:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2015/03/10/423344.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/423344.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2015/03/10/423344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/423344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/423344.html</trackback:ping><description><![CDATA[Eclipse有个功能就是把整个项目打包成一个可执行的Jar文件，里面包含了所有项目引用了的库，如果电脑上安装了JRE，直接双击就可以启动，看起来很方便，如下图所示：<br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/amplifier/导出1.JPG" height="547" width="626" /><br />可以选择把所有类库打包进去，也就是Jar里面还包含一堆Jar：<br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/amplifier/导出2.JPG" height="110" width="450" /><br />还可以生成ant脚本：<br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/amplifier/ant.JPG" height="50" width="141" /><br /><br />生成的jar文件，可以直接通过java -jar xx.jar启动，简单快捷。<br /><br /><br />然而，这样导出来的可执行jar，启动速度却非常慢，这跟包的大小有关。有个项目导出来的包有40MB，结果启动需要近一分钟，在性能差的电脑上，甚至要几分钟，就是你执行完命令后，没有任何界面显示，但是查看任务管理器发现java进程的CPU占用率在浮动，说明正在努力启动，过了一段时间之后界面突然显示出来，简直让人崩溃。可是在Eclipse里面运行，却是一点就开。<br /><br />我开始尝试缩小导出的包。但是Eclipse的导出对话框并没有提供需要打包哪些库的选项，都是默认把所有库都打包进去，但是它可以生成ant脚本，可以通过编辑ant脚本的方式来减少不必要的库。经过多次尝试，终于把40MB的包缩成了17MB，启动速度快了一些，但是依然需要半分钟以上。<br /><br />后来觉得，能不能不打包直接运行呢？于是把导出来的包用压缩软件解压，再把里面包含的jar包继续解压，最后得到一堆没有压缩的class文件，再通过指定classpath的方式，直接运行程序入口class，发现启动速度和在Eclipse里面一样，一点就开。<br /><br />打包的好处是部署简单，只需要一个文件，但带来的缺点实在不能忍，打散的方式部署起来稍微难一点，但是启动速度够快，对普通用户来说，这个才是最重要的。<br /><br />当然，还有一种方式是像Eclipse那样，启动时显示一个图片，底下一个进度条显示启动进度，不过这样也加大了工作量，而且每次都要等那进度条，实际上也很烦。<img src ="http://www.blogjava.net/amplifier/aggbug/423344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2015-03-10 15:07 <a href="http://www.blogjava.net/amplifier/archive/2015/03/10/423344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JavaVC替换JMF连接摄像头</title><link>http://www.blogjava.net/amplifier/archive/2015/02/15/422936.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Sun, 15 Feb 2015 03:41:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2015/02/15/422936.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/422936.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2015/02/15/422936.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/422936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/422936.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JMF太老了，各种问题得不到解决，Oracle也没再升级过，如果能找到新东西，最好能把它扔掉。最近OpenCV比较火，还有人用Java封装了OpenCV，成立了JavaCV项目，通过改造VideoInput这个基于C语言的项目，能够用Java来调用摄像头，JMF可以扔掉了。如果想测试，非常简单，把那些编译好的jar文件放入Build Path即可，如果是在Windows X86环境下，则只需要把带...&nbsp;&nbsp;<a href='http://www.blogjava.net/amplifier/archive/2015/02/15/422936.html'>阅读全文</a><img src ="http://www.blogjava.net/amplifier/aggbug/422936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2015-02-15 11:41 <a href="http://www.blogjava.net/amplifier/archive/2015/02/15/422936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JMF找不到摄像头的解决方法</title><link>http://www.blogjava.net/amplifier/archive/2014/07/01/415330.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 01 Jul 2014 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2014/07/01/415330.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/415330.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2014/07/01/415330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/415330.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/415330.html</trackback:ping><description><![CDATA[JMF（Java Media Framework）是Java平台使用摄像头、麦克风等媒体设备的应用程序框架，但到了2.1.1e就不再更新，在Windows 7 X64上还能正常运行，只是安装的界面让你感觉回到了Windows98的时代。<br /><br /><br />不过年代久远的东西，虽然还能用，但可能会遇到一些奇怪的问题，折腾了两个月，发现了两个比较大的问题：<br /><br />第一个是在Windows 7 x64上提示摄像头初始化失败的问题。这个问题很奇怪，电脑刚开机的时候可以顺利找到一次摄像头并正常操作，但是第二次就会提示摄像头初始化失败。有人提出的解决方法是安装一个叫ManyCamera的程序，这个程序可以把一个摄像头供多个程序同时使用，其实就等于中间加了一层转换，效果会有点差别，免费版还会加上水印，要求比较高的人可能会不爽，但是目前找不到其他办法。<br /><br />第二个是在程序中找不到摄像头，不光找不到摄像头，其他媒体设备通通找不到，使用以下语句：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; "></span> <span style="color: #000000; ">vector&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;CaptureDeviceManager.getDeviceList&nbsp;(&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">&nbsp;)</span></div>按照文档说明是返回所有媒体设备，但每次vector都是null。<br />在Eclipse中运行又能正常，导出成jar之后运行就会找不到摄像头。<br />原因在于找不到jmf.properities文件，该文件包含所有检测到的媒体设备的信息，<strong>最简单的解决方法就是把JMF安装目录下lib子目录中的jmf.properties文件复制到最后运行的jar所在的目录</strong>，不过如果摄像头改过的话，重新检测后要把新的文件复制到jar目录，因为检测到的媒体设备信息都会存放在JMF安装目录里面的jmf.properties文件里。<br /><div><br />StackOverflow里面有个人对这个问题解释得比较清楚：<br /><a target="_blank" href="http://stackoverflow.com/questions/8768142/java-capturedevicemanagergetdevicelist-is-empty">http://stackoverflow.com/questions/8768142/java-capturedevicemanagergetdevicelist-is-empty</a></div><br /><br />虽然问题解决了，但是还是不明白为何在Eclipse中可以正常运行，导出jar后运行却找不到摄像头，即使把JMF所有jar和lib目录都加入系统的CLASSPATH环境变量里还是不行。<br /><br /><br />另外，JMF安装程序会自动把它的jar和lib目录加入系统的%CLASSPATH%环境变量，但是如果你卸载了再重新安装到其他目录，并不会改变%CLASSPATH%的值，需要手动修改。不过这个环境变量似乎没啥用处。<br />最好不要把JMF安装到默认的Program Files目录，可能会运行不了，安装到短目录会比较保险，它似乎还是只认Dos时代的8.3目录结构，但偏偏又默认安装到Program Files里面。<br /><img src ="http://www.blogjava.net/amplifier/aggbug/415330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2014-07-01 10:33 <a href="http://www.blogjava.net/amplifier/archive/2014/07/01/415330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android手机用来做电脑摄像头</title><link>http://www.blogjava.net/amplifier/archive/2014/06/05/414431.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 05 Jun 2014 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2014/06/05/414431.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/414431.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2014/06/05/414431.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/414431.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/414431.html</trackback:ping><description><![CDATA[现在的手机摄像头动辄几百万上千万像素，如果电脑需要用到摄像头又没有的话，不妨用手机的摄像头代替。<br /><br />我是在做一个电脑二维码识别器的时候，因为原来的摄像头太差，从而想到用一台淘汰的Android手机来代替。<br /><br />这类应用应该不少，我首先找到的是一个叫DraoidCam的应用，装好之后发现免费版没法调整分辨率，于是放弃之。<br /><br />然后又找到了一个国内做的免费软件，叫魅色，非常简单，支持USB和WiFi连接方式，如果是USB连接的话，打开USB调试模式之后，运行电脑的客户端，手机上就自动装上了App并且自动运行，可以调整分辨率，不过最高只有640*480，帧率不到10，不过已经能够满足我的需求了。<br /><br />然后就可以像普通PC摄像头一样使用了，在JMF里面也能找到，于是就可以被Java调用了。经测试，效果比原来的PC摄像头好多了。<br /><br />软件主页：<a target="_blank" href="http://www.libfetion.org/meise/ ">http://www.libfetion.org/meise/ </a><img src ="http://www.blogjava.net/amplifier/aggbug/414431.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2014-06-05 15:35 <a href="http://www.blogjava.net/amplifier/archive/2014/06/05/414431.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的位操作</title><link>http://www.blogjava.net/amplifier/archive/2012/04/08/373574.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Sun, 08 Apr 2012 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2012/04/08/373574.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/373574.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2012/04/08/373574.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/373574.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/373574.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;">当读写二进制文件，或者要把非标准长度的整数与标准长度的整数互相转换时，就要用到大量的位操作，虽然看起来很简单，实际上里面却有很多细节很容易出错。</span><br /><br /><strong><span style="font-size: 10pt;">首先，Java有些标准跟C/C++是不同的：</span></strong><br /><br /><span style="font-size: 10pt;">1、Java采用高字节在前的方式读写数据，例如要把一个4字节的int数值写入文件时，它是按照从高字节到低字节的顺序写入的，读取的时候也是这样读出来。</span><br /><span style="font-size: 10pt;">而C/C++则采用平台相关的方式，在Windows平台采用低字节在前的方式，在Linux/Unix平台则采用高字节在前的方式。</span><br /><span style="font-size: 10pt;">如果Java要读取C/C++创建的二进制文件，就要注意这个问题，最好先搞清楚原来的文件是采用哪种方式创建的。网络通信也要注意。</span><br /><br /><span style="font-size: 10pt;">2、Java没有无符号数，无论byte,short,int,long都是有符号整数，而C/C++有个unsigned关键字可以设置一个数值为无符号数。</span><br /><br /><span style="font-size: 10pt;">3、Java的整数基本数据类型就是byte,short,int,long这几个，长度分别为1,2,4,8字节，C/C++可以用typedef定义各种数据类型。</span><br /><br /><span style="font-size: 10pt;"><strong>第二，Java是采用补码来存放整数的。</strong><br />有时候觉得补码的定义有些奇怪，实际上可以这样理解：</span><br /><span style="font-size: 10pt;">把一个整数从0一直往上加1，加到溢出就变成了负数的最小值，然后再继续加1，最后又能回到0，实际上就是一个轮回。</span><br /><span style="font-size: 10pt;">例如一个byte类型的整数，一共有8位，能表示256个数值，采用补码的话数值范围就是-128~127，表示方法如下：</span><br /><span style="font-size: 10pt;">0&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0000 0000</span><br /><span style="font-size: 10pt;">1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0000 0001</span><br /><span style="font-size: 10pt;">.</span><br /><span style="font-size: 10pt;">.</span><br /><span style="font-size: 10pt;">126&nbsp;&nbsp;&nbsp; 0111 1110</span><br /><span style="font-size: 10pt;">127&nbsp;&nbsp;&nbsp; 0111 1111</span><br /><span style="font-size: 10pt;">-128&nbsp;&nbsp; 1000 0000</span><br /><span style="font-size: 10pt;">-127&nbsp;&nbsp; 1000 0001</span><br /><span style="font-size: 10pt;">.</span><br /><span style="font-size: 10pt;">.</span><br /><span style="font-size: 10pt;">-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1111 1111</span><br /><span style="font-size: 10pt;">0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0000 0000</span><br /><br /><strong><span style="font-size: 10pt;">第三、不同长度的整数转换。</span></strong><br /><span style="font-size: 10pt;">如果是从较短的数转成较长的数，很简单，如果是正数就在高字节补0，如果是负数就在高字节补1。 </span><br /><span style="font-size: 10pt;">例如byte的127转为short的127：</span><br /><span style="font-size: 10pt;">byte:0111 1111</span><br /><span style="font-size: 10pt;">short:0000 0000 0111 0111</span><br /><span style="font-size: 10pt;">byte的-127转为short的-127</span><br /><span style="font-size: 10pt;">byte:1000 0001</span><br /><span style="font-size: 10pt;">short:1111 1111 1000 0001</span><br /><span style="font-size: 10pt;">如果是从较长的数转成较短的数，实际上就是把高位都截断了，所以转出来的数值可能完全不是一回事了。</span><br /><span style="font-size: 10pt;">例如short的256转为byte：</span><br /><span style="font-size: 10pt;">short:0000 0001 0000 0000</span><br /><span style="font-size: 10pt;">byte: 0000 0000</span><br /><span style="font-size: 10pt;">把256变成了0</span><br /><span style="font-size: 10pt;">short的-255转成byte:</span><br /><span style="font-size: 10pt;">short:1111 1111 0000 0001</span><br /><span style="font-size: 10pt;">byte:0000 0001</span><br /><span style="font-size: 10pt;">把-255变成了1</span><br /><br /><strong><span style="font-size: 10pt;">第四、位运算操作符及它们的优先级</span></strong><br /><span style="font-size: 10pt;">Java的位运算操作符包括：~非，|按位或，&amp;按位与，^按位异或，&lt;&lt;左移，&gt;&gt;右移，&gt;&gt;&gt;右移左侧补0</span><br /><span style="font-size: 10pt;">各种运算符的优先级如下表所示：</span><br /><div><table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"><div align="center"><span style="font-size: 10pt;">优先级</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">运算符</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: black 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div align="center"><span style="font-size: 10pt;">结合性</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">1</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">() [] .</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左到右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">2</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">! +(正)  -(负) ~ ++ --</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从右向左</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">3</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">* / %</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">4</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">+(加) -(减)</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">5</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">&lt;&lt; &gt;&gt; &gt;&gt;&gt;</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">6</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">&lt; &lt;= &gt; &gt;= instanceof</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">7</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">==   !=</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">8</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">&amp;(按位与)</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">9</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">^</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">10</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">|</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">11</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">&amp;&amp;</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">12</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">||</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从左向右</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">13</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">?:</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="85"> <div><span style="font-size: 10pt;">从右向左</span></div></td></tr> <tr> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: black 1pt solid; width: 42.55pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="57"> <div align="center"><span style="font-size: 10pt;">14</span></div></td> <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 169.8pt; padding-top: 0cm; border-bottom: black 1pt solid" valign="top" width="226"> <div align="center"><span style="font-size: 10pt;">= += -= *= /= %= &amp;= |= ^=  ~=  &lt;&lt;= &gt;&gt;=   &gt;&gt;&gt;=</span></div></td> <td style="border-right: black 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 64.05pt; padding-top: 0cm; border-bottom: black 1pt solid" width="85"> <div><span style="font-size: 10pt;">从右向左</span></div></td></tr></tbody></table></div><span style="font-size: 10pt;">根据该表可以看到，位运算操作符的优先级各有不同，分别为：</span><br /><span style="font-size: 10pt;">1、~</span><br /><span style="font-size: 10pt;">2、&gt;&gt; &lt;&lt; &gt;&gt;&gt;</span><br /><span style="font-size: 10pt;">3、&amp;</span><br /><span style="font-size: 10pt;">4、^</span><br /><span style="font-size: 10pt;">5、|</span><br /><span style="font-size: 10pt;">另外需要特别注意的是，除了~，其他位运算操作的优先级都低于加减，所以要记得以下语句是返回32而不是7！</span><br /><span style="font-size: 10pt;">1&lt;&lt;2+3</span><br /><span style="font-size: 10pt;">还有就是&amp;、^、|的优先级都是低于逻辑操作符的，因此下面的语句会编译出错，幸好Java不像C那样对所有大于1的值都认为是真，否则下面的语句也能编译通过，但可能与你的意图不太一样，可能调试半天才发现。</span><br /><span style="font-size: 10pt;">if(3&amp;1&gt;0)</span><br /><span style="font-size: 10pt;">如果记不清楚，还是按照你的意图加上括号最保险。</span><br /><br /><strong><span style="font-size: 10pt;">第五、字节数组与整数之间的转换</span></strong><br /><span style="font-size: 10pt;">为了把一个整数存入文件，或者从文件中读取一个整数，需要经常在字节数组和整数之间转换，这个过程要用到大量的位运算。</span><br /><span style="font-size: 10pt;">首先需要记住的是，在参与所有运算前，Java都会把byte、short类型的值都转换成int，然后再对转换后的int进行操作。例如下面的语句会编译出错：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">&nbsp;a</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">10</span><span style="color: #000000; font-size: 10pt;">,b</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">20</span><span style="color: #000000; font-size: 10pt;">,c;<br /></span><span style="color: #000000; font-size: 10pt;">c</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">a</span><span style="color: #000000; font-size: 10pt;">+</span><span style="color: #000000; font-size: 10pt;">b;</span></div><br /><span style="font-size: 10pt;">因为a和b在相加前都被转成了int，最后得到的结果是个int类型的值，如果要赋给byte类型的c，必须显式地进行类型转换，即把第二句改为：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">c</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">)(a</span><span style="color: #000000; ">+</span><span style="color: #000000; ">b)</span></div><br /><span style="font-size: 10pt;">这一点很关键，因为对于一个最高位为1的byte类型的整数（负数），在运算之前它会被强制转换成int类型，根据上面所说的第三点，其实就是往前面的三个高字节补上1，这样一来，它在参与位运算的过程中，就不仅仅是它本身的8个bit参与了，实际上连前3个字节的24个bit（均为1）也参与了。例如有一个整数i=1082163328，它的二进制表示为：</span><div><span style="font-size: 10pt;">01000000 10000000 10000000 10000000</span><br /><span style="font-size: 10pt;">分为4个字节存储，除了第一个字节是正数外，其余3个字节均为负数。假如用a代表最高字节的值，用b代表其他三个字节的值，如果按照通常的理解，你可能会这样得到i的值：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(a</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">24</span><span style="color: #000000; ">)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">(b</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">16</span><span style="color: #000000; ">)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">(b</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">b</span></div><br /><span style="font-size: 10pt;">如果a和b都是正数，上面的等式是成立的，但是在这个例子里，却是错的，因为上式中的a和b都已经被强制转换成了int类型再参加运算，实际上</span><br /><span style="font-size: 10pt;">a=00000000 00000000 00000000 01000000</span><br /><span style="font-size: 10pt;">b=11111111 11111111 11111111 10000000</span><br /><span style="font-size: 10pt;">i=01000000 00000000 00000000 00000000+11111111 10000000 00000000 00000000+11111111 11111111 10000000 00000000+11111111 11111111 11111111 10000000</span></div><span style="font-size: 10pt;">最后得到的结果是1065320320，不是原来的值了。</span><br /><span style="font-size: 10pt;">为了不让byte在强制转换成int的过程加入了我们不想要的高位1，我们需要把它跟0xff进行与操作，i的值应该这样运算：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(&nbsp;(&nbsp;a</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">24</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">(&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">16</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)</span></div><br /><span style="font-size: 10pt;">注意，因为&amp;和&lt;&lt;的优先级都低于+，所以上面的括号是不能少的。不过由于跟0xff与操作之后，其余24位都变成了0，因此可以把+改为|操作，因为任何值与0进行或操作都得到本身：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(&nbsp;a&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">24</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">16</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)</span></div><br /><span style="font-size: 10pt;">由于&lt;&lt;的优先级高于|，所以省了一些括号。最高字节可以不与0xff进行与操作，因为它转换成int后左边增加的3个字节都在左移24位时被去掉了：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">24</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">16</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">&nbsp;)</span></div><br /><br /><span style="font-size: 10pt;">把int转为字节数组的时候比较简单，直接右移截断即可：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">[]&nbsp;b&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt;">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">[</span><span style="color: #000000; font-size: 10pt;">4</span><span style="color: #000000; font-size: 10pt;">];<br /></span><span style="color: #000000; font-size: 10pt;">b[</span><span style="color: #000000; font-size: 10pt;">0</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">&nbsp;(</span><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">)&nbsp;(i&nbsp;</span><span style="color: #000000; font-size: 10pt;">&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">24</span><span style="color: #000000; font-size: 10pt;">);<br /></span><span style="color: #000000; font-size: 10pt;">b[</span><span style="color: #000000; font-size: 10pt;">1</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">&nbsp;(</span><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">)&nbsp;(i&nbsp;</span><span style="color: #000000; font-size: 10pt;">&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">16</span><span style="color: #000000; font-size: 10pt;">);<br /></span><span style="color: #000000; font-size: 10pt;">b[</span><span style="color: #000000; font-size: 10pt;">2</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">&nbsp;(</span><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">)&nbsp;(i&nbsp;</span><span style="color: #000000; font-size: 10pt;">&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">8</span><span style="color: #000000; font-size: 10pt;">);<br /></span><span style="color: #000000; font-size: 10pt;">b[</span><span style="color: #000000; font-size: 10pt;">3</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">&nbsp;(</span><span style="color: #0000ff; font-size: 10pt;">byte</span><span style="color: #000000; font-size: 10pt;">)&nbsp;i;</span></div><br /><br /><strong><span style="font-size: 10pt;">第六、非标准长度整数的存储和读取</span></strong><br /><span style="font-size: 10pt;">假如有两个变量，他们的值可以用12个bit来表示，如果我们用16bit的short类型来表示一个变量，那么两个变量就需要4个字节，而实际上它们只需要3个字节就能表示出来，如果存储空间比较有限，写入文件时可以把它们存放在3个字节里面，但是读写过程就需要进行转换。</span><br /><span style="font-size: 10pt;">在内存里，它们都是标准的数据类型：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">short</span><span style="color: #000000; ">&nbsp;a,b;</span></div><br /><span style="font-size: 10pt;">写入文件时，我们用第一个字节和第二个字节的前半部分来表示a，把第二个字节的后半部分和第三个字节</span><span style="font-size: 10pt;">来表示b，即：</span><br /><span style="font-size: 10pt;">1：xxxx xxxx</span><br /><span style="font-size: 10pt;">2：xxxx yyyy</span><br /><span style="font-size: 10pt;">3：yyyy yyyy</span><br /><span style="font-size: 10pt;">x和y都表示一个bit，分别用来存放a和b。写入时先把a和b转为字节数组：</span><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">[]&nbsp;out&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">[</span><span style="color: #000000; ">3</span><span style="color: #000000; ">];<br />out[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">)&nbsp;(&nbsp;a&nbsp;</span><span style="color: #000000; ">&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">4</span><span style="color: #000000; ">&nbsp;);</span><span style="color: #008000; ">//</span><span style="color: #008000; ">把a的高8位放在第一个字节</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">out[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">)&nbsp;(&nbsp;a&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">4</span><span style="color: #000000; ">&nbsp;);</span><span style="color: #008000; ">//</span><span style="color: #008000;">先把a左移四位，在右边补上4个0，第二个字节的高4位就是a的低4位了，第二个字节的高4位已经生成，低4位还是0</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">out[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">|=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">)&nbsp;(&nbsp;b&nbsp;</span><span style="color: #000000; ">&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0x0f</span><span style="color: #000000; ">&nbsp;);</span><span style="color: #008000; ">//</span><span style="color: #008000; ">b右移8位，并与0x0f进行与操作，实际上就只保留了b的高4位，并且是在字节的低4位上，跟第二步得到的字节进行或操作，就生成了第二个字节</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">out[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">byte</span><span style="color: #000000; ">)&nbsp;b;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">把b的高4位截断就得到了低8位</span></div><span style="font-size: 10pt;">然后再把这个字节数组写入文件，就可以用3个字节表示两个整数了。</span><br /><span style="font-size: 10pt;">读取：</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; font-size: 10pt;">a&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;">(short)( (out[</span><span style="color: #000000; font-size: 10pt;">0</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">0xff</span><span style="color: #000000; font-size: 10pt;">)&nbsp;</span><span style="color: #000000; font-size: 10pt;">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">4</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">|</span><span style="color: #000000; font-size: 10pt;">&nbsp;(&nbsp;out[</span><span style="color: #000000; font-size: 10pt;">1</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">0xf0</span><span style="color: #000000; font-size: 10pt;">&nbsp;)</span><span style="color: #000000; font-size: 10pt;">&gt;&gt;</span><span style="color: #000000; font-size: 10pt;">4</span><span style="color: #000000; font-size: 10pt;">);<br /></span><span style="color: #000000; font-size: 10pt;">b&nbsp;</span><span style="color: #000000; font-size: 10pt;">=</span><span style="color: #000000; font-size: 10pt;"> (short)((out[</span><span style="color: #000000; font-size: 10pt;">1</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">0x0f</span><span style="color: #000000; font-size: 10pt;">)&nbsp;</span><span style="color: #000000; font-size: 10pt;">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">8</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">|</span><span style="color: #000000; font-size: 10pt;">&nbsp;(&nbsp;out[</span><span style="color: #000000; font-size: 10pt;">2</span><span style="color: #000000; font-size: 10pt;">]&nbsp;</span><span style="color: #000000; font-size: 10pt;">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 10pt;">0xff</span><span style="color: #000000; font-size: 10pt;">));</span></div><img src ="http://www.blogjava.net/amplifier/aggbug/373574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2012-04-08 16:56 <a href="http://www.blogjava.net/amplifier/archive/2012/04/08/373574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用JAVA做一个便宜好用的二维码扫描器</title><link>http://www.blogjava.net/amplifier/archive/2009/04/02/263567.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 02 Apr 2009 08:22:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2009/04/02/263567.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/263567.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2009/04/02/263567.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/263567.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/263567.html</trackback:ping><description><![CDATA[
		<p>二维条形码比普通的条形码能保存更多的信息，已经应用到很多领域里面。例如手机电影票，就是一个嵌在彩信里面的二维码图像。南航也推出了网上办理登机牌业务，办理完成之后往手机发送一条包含二维码的彩信，到了机场就可以通过自助设备扫描二维码，打印登机牌。<br />然而，专业的二维码扫描设备价格十分昂贵，最便宜的都在1000元以上，到淘宝上搜搜就知道了。借助Java和一个开源的库，我们却可以通过普通的网络摄像头实现相同的效果，成本只需要几十块。<br /><a id="label-0" name="label-0">Open Source QR Code Library</a>是一个开源的QR Code（二维条形码的一种）生成和读取的库，官方网站为：<a href="http://qrcode.sourceforge.jp/">http://qrcode.sourceforge.jp/</a>，里面包含了生成和读取QR Code的所有代码，其中有个jmfexample就能实现通过摄像头读取QR Code，经过本人尝试，几十块的普通摄像头效果已经不错了，一次读取几百字节都没问题。<br />使用这个库的步骤如下：<br />1、到其官方网站下载回来；<br />2、到sun的网站下载JMF包并安装；<br />3、插上摄像头，打开我的电脑，查看是否出现“USB视频设备”，然后打开，看摄像头工作是否正常<br />4、运行JMF里面的JMF Registry程序，点击“Detect Capture Devices”，查找视频设备，查找到之后会在左边的列表里出现“vfw:Microsoft WDM Image Capture (Win32):0”类似的设备，点击就会在右边出现其详细信息，我的摄像头是这样的：<br /><em>Name = vfw:Microsoft WDM Image Capture (Win32):0</em></p>
		<p>
				<em>Locator = vfw://0</em>
		</p>
		<p>
				<em>Output Formats----&gt;</em>
		</p>
		<p>
				<em>0. javax.media.format.YUVFormat<br />  YUV Video Format: Size = java.awt.Dimension[width=640,height=480] MaxDataLength = 614400 DataType = class [B yuvType = 32 StrideY = 1280 StrideUV = 1280 OffsetY = 0 OffsetU = 1 OffsetV = 3</em>
		</p>
		<p>
				<em>1. javax.media.format.YUVFormat<br />  YUV Video Format: Size = java.awt.Dimension[width=160,height=120] MaxDataLength = 38400 DataType = class [B yuvType = 32 StrideY = 320 StrideUV = 320 OffsetY = 0 OffsetU = 1 OffsetV = 3</em>
		</p>
		<p>
				<em>2. javax.media.format.YUVFormat<br />  YUV Video Format: Size = java.awt.Dimension[width=176,height=144] MaxDataLength = 50688 DataType = class [B yuvType = 32 StrideY = 352 StrideUV = 352 OffsetY = 0 OffsetU = 1 OffsetV = 3</em>
		</p>
		<p>
				<em>3. javax.media.format.YUVFormat<br />  YUV Video Format: Size = java.awt.Dimension[width=320,height=240] MaxDataLength = 153600 DataType = class [B yuvType = 32 StrideY = 640 StrideUV = 640 OffsetY = 0 OffsetU = 1 OffsetV = 3</em>
		</p>
		<p>
				<em>4. javax.media.format.YUVFormat<br />  YUV Video Format: Size = java.awt.Dimension[width=352,height=288] MaxDataLength = 202752 DataType = class [B yuvType = 32 StrideY = 704 StrideUV = 704 OffsetY = 0 OffsetU = 1 OffsetV = 3</em>
		</p>
		<p>注意，其中Output Formats都是javax.media.format.YUVFormat，而QR Code Library里默认的设备不是这种格式的，所以需要对源码作一定的修改。<br /><br />5、用Eclipse打开QR Code Library的源码，作出一些适当的修改：<br />如果摄像头是上面所说的只支持YUV格式，则需要修改jp.sourceforge.qrcode.example.jmf.camDataSource.java，把setMainSource函数里的<br />VideoFormat vidformat = new VideoFormat(VideoFormat.RGB);<br />修改为<br />VideoFormat vidformat = new VideoFormat(VideoFormat.YUV);<br />否则永远也找不到摄像头。<br /><br />6、把JMF包里的jmf.jar放到Classpath里<br />7、执行jp.sourceforge.qrcode.example.jmf.jmfexample，搞定<br /><br />当然，由于源码开放的，只要符合许可，你想怎么改都行，可以把它嵌入到某个应用程序里面，这个程序就具有了扫描QR Code的功能了。<br /><br /></p>
<img src ="http://www.blogjava.net/amplifier/aggbug/263567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2009-04-02 16:22 <a href="http://www.blogjava.net/amplifier/archive/2009/04/02/263567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用NOKIA MMS LIBRARY发送中国移动彩信</title><link>http://www.blogjava.net/amplifier/archive/2008/06/17/208620.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 17 Jun 2008 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2008/06/17/208620.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/208620.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2008/06/17/208620.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/208620.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/208620.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Nokia MMS Library是一个开放源代码的Java MMS开发包，里面包含了源码、文档、示例程序等，很容易就能学会。下面是用这个包发送彩信的方法：1、电脑通过GPRS/EDGE MODEM或手机连接移动梦网，注意，必须是移动梦网（CMWAP），不是互联网（CMNET），如果手动拨号，一般是拨*99***1#或*99***2#，拨通之后打开命令行窗口，telnet 10.0.0.172...&nbsp;&nbsp;<a href='http://www.blogjava.net/amplifier/archive/2008/06/17/208620.html'>阅读全文</a><img src ="http://www.blogjava.net/amplifier/aggbug/208620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2008-06-17 14:35 <a href="http://www.blogjava.net/amplifier/archive/2008/06/17/208620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的线程重启</title><link>http://www.blogjava.net/amplifier/archive/2008/04/22/194710.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 22 Apr 2008 02:56:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2008/04/22/194710.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/194710.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2008/04/22/194710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/194710.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/194710.html</trackback:ping><description><![CDATA[刚刚才知道，原来Java的线程是不能重启的，也就是说，当线程的run()方法执行到最后一行，退出之后，这个线程就结束了，不能再通过start()方法重启启动这个线程，只能重新构造一个线程对象，再调用其start()方法来启动，但这个对象和原来那个对象已经不同了。<br />
为了实现某个线程对象的&#8220;重启&#8221;功能，可以在它的run()方法的最外层加上一个循环语句：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;run(){<br />
</span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">(</span><span style="color: #000000">!</span><span style="color: #000000">stop){<br />
</span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">do&nbsp;something</span><span style="color: #008000"><br />
</span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;}<br />
</span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">}</span></div>
<br />
这样，只要stop不为true，run()方法就不会结束，不断地&#8220;重启&#8221;。<br />
如果run()方法里面还有一个循环，那么就要两个停止标志：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;run(){<br />
</span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">(</span><span style="color: #000000">!</span><span style="color: #000000">stop){<br />
</span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">do&nbsp;something</span><span style="color: #008000"><br />
</span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">(</span><span style="color: #000000">!</span><span style="color: #000000">stop&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">restart){<br />
</span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">do&nbsp;other&nbsp;thing</span><span style="color: #008000"><br />
</span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;}<br />
</span><span style="color: #008080">8</span>&nbsp;<span style="color: #000000">}<br />
</span><span style="color: #008080">9</span>&nbsp;</div>
这样，如果需要&#8220;重启&#8221;线程，只要把restart设为true即可，如果要退出线程，只要把stop设为true即可。
<img src ="http://www.blogjava.net/amplifier/aggbug/194710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2008-04-22 10:56 <a href="http://www.blogjava.net/amplifier/archive/2008/04/22/194710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过程序发送彩信——利用Now SMS/MMS和Apache HttpClient</title><link>http://www.blogjava.net/amplifier/archive/2007/10/01/150047.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Mon, 01 Oct 2007 06:22:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/10/01/150047.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/150047.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/10/01/150047.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/150047.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/150047.html</trackback:ping><description><![CDATA[有时候我们需要通过程序自动发送一些纯文字的信息，通过SMS可以达到目的，但当文字达到一定长度时，就必须分割成多条短信（一般60汉字一条），增加了费用，通过MMS可以解决这一问题，MMS最大支持100KB的内容，假设每个汉字3byte（使用UTF-8编码），能发送33K个汉字，一次可以发送一篇文章了。<br />
Now SMS/MMS提供了一个Web界面用于发送彩信，通过Apache HttpClient，我们可以模拟浏览器的行为向web服务器提交表单，发送彩信。Now SMS/MMS的Web界面提供了很多选项，但发送纯文字彩信的话我们只需要填写接收者，主题（可选），内容即可，把对应的表单内容POST到当前页面，就能发送一条彩信。（待续）
<img src ="http://www.blogjava.net/amplifier/aggbug/150047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-10-01 14:22 <a href="http://www.blogjava.net/amplifier/archive/2007/10/01/150047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Now SMS/MMS 发送中国移动彩信</title><link>http://www.blogjava.net/amplifier/archive/2007/09/18/146235.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 18 Sep 2007 11:32:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/09/18/146235.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/146235.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/09/18/146235.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/146235.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/146235.html</trackback:ping><description><![CDATA[<a href="http://www.nowsms.com" target="_blank">Now SMS/MMS</a>是一个强大的短信/彩信发送服务器，它内置了彩信中心，在某些运营商的网络内可以通过普通的短信猫发送彩信，而不需要使用支持GPRS的短信猫，也就是说系统本身就具有了运营商的彩信中心的功能。然而，在中国移动的网络内是不能实现这种方式发送彩信的，必须通过移动梦网的彩信中心转发。<br />
彩信的发送其实是两个过程：<br />
1、向目标手机发送一条普通的提醒短信，其中包含了发送者号码、彩信的URL等信息，该URL指向彩信中心的某个web目录下的某个彩信文件；<br />
2、目标手机接收到这条提醒短信后，主动发起GPRS连接，根据短信中的URL向彩信中心提取该彩信，并显示出来。<br />
Now SMS/MMS 自带的彩信中心其实就是一个支持手机连接的web服务器，它把制作好的彩信放在某个web目录下，手机连接时就可以下载。<br />
然而，实践证明，如果使用中国移动的SIM卡，无论使用的是什么短信猫，都不能通过系统自带的彩信中心发送彩信。<br />
要设置成通过移动公司的彩信中心发送彩信，必须把系统的默认设置——使用自带的MMSC（彩信中心）——改为使用移动公司的MMSC。方法如下：<br />
在Now SMS/MMS Gateway配置程序中选择MMSC Routing，然后点击Add按钮，在弹出的对话框中建立一个新的MMSC配置，其中Acount Name和Account Description可以随便填，只是用来识别配置名称，因为系统可以设置多个MMSC。<span style="color: #ff0000">Default Sender Address必须留空，否则发送很难成功（有极少部分能够发送成功）。Allow Sender Address Override前的复选框也必须留空。Route messages to this account for recipient phone number(s)不用填（这是一个掩码，只有符合要求的号码才用这个路由，按照官方文档的说法，不填的话是不会用这个路由的，但实际上把它设成默认路由的话，即使不填也会用这个，也许填上+861*,1*会好些，表示中国的手机都用这个发）。Route messages to VASP via选择MM1，之后会出现更多的输入框，点击Look up Operator Seetings，出现一个选择运营商的对话框，很幸运，中国移动在里面，选择China - China Mobile，然后OK即可，系统自动把适合中国移动的内容填了进去。但是Network Connection和Modem Used两个下拉列表还没选好。这里必须使用对应的GPRS猫的调制解调器（在控制面板-电话和调制解调器选项-调制解调器-添加，按照提示一步步就能找到GPRS猫，看好哪个调制解调器对应哪个端口，从而知道哪个调制解调器对应哪个GPRS猫）。填好这些东西后点击Test Connection可以检测连接，成功就可以了，检测时间比较长，要耐心等待。填好之后点击OK，在MMSC Routing标签页里的Additional Routes里面就能看到刚才的那个配置名称，然后在Default Route里面选择刚才的配置名称作为默认路由就可以了。<br />
<span style="color: #000000">之后打开MMSC标签，配置自带的MMSC。虽然我们使用的是中国移动的MMSC，但通过web发送彩信时，必须先发送到系统自带的MMSC，再转发到移动的MMSC，所以必须把系统的MMSC也配置好。这里就是普通web服务器的配置（还有SMTP的配置，可选），把端口和IP选好后，还要注意Local Host Name or IP Address里要填入一个本机的IP，如果在仅在内网使用，可以直接填本机IP（外网的情况没有研究过，看看说明书先）。其他默认的就可以了。<br />
再打开Web标签页，把Web服务器配置好。<br />
打开浏览器，输入http://服务器IP:web服务器端口/，就能看到发送各种短信、彩信的链接，然后就可以发送彩信进行测试了。如果发送不成功，可以打开Serial #标签页，把底下的三个Debug选项都勾上，再发送一下，然后在Now SMS/MMS 的安装目录下找到MMSCDEBUG.LOG等几个LOG文件查看究竟是什么问题。文件太大会导致发送失败，系统不会自动检查的。文件大小的上限还不清楚，但超过100KB似乎就肯定不行。<br />
今天搞了一天这个东西，终于能正常发送彩信了。在这里备忘一下。慢慢再作深入研究。</span></span> <br />
<br />
感谢：<a href="http://blog.csdn.net/phiger/archive/2006/12/19/1449176.aspx " target="_blank">http://blog.csdn.net/phiger/archive/2006/12/19/1449176.aspx </a><br />
<br />
官方文档：<a href="http://www.nowsms.com/documentation/http://www.nowsms.com/documentation/ProductDocumentation/mms_notifications_and_content/Connecting_to_operator_MMSC.htm#SendingMMSMessagesProductDocumentation/mms_notifications_and_content/Connecting_to_operator_MMSC.htm#SendingMMSMessages">http://www.nowsms.com/documentation/ProductDocumentation/mms_notifications_and_content/Connecting_to_operator_MMSC.htm#SendingMMSMessages</a> 
<img src ="http://www.blogjava.net/amplifier/aggbug/146235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-09-18 19:32 <a href="http://www.blogjava.net/amplifier/archive/2007/09/18/146235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何判断Socket已断开</title><link>http://www.blogjava.net/amplifier/archive/2007/04/12/110131.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 12 Apr 2007 04:21:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/04/12/110131.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/110131.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/04/12/110131.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/110131.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/110131.html</trackback:ping><description><![CDATA[<p>打开了连接服务器的一个Socket后，隔了一段时间没用，Socket就会自动关闭（为什么？），这时候如果获取该Socket的OutputStream，并往里面写东西，在flush的时候就会出现：<br>java.net.SocketException: Software caused connection abort: socket write error<br>的异常。因此，如果隔了一段时间没有使用某个Socket，需要重新使用它的时候，就要先判断它究竟是否还在连接当中，一共尝试了Socket的三个方法：<br>1、<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Socket.html#isClosed()"><strong><u><font face="Courier New" color=#800080>isClosed</font></u></strong></a><font face="Courier New">()</font> <br>2、<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Socket.html#isOutputShutdown()"><strong><u><font face="Courier New" color=#800080>isOutputShutdown</font></u></strong></a><font face="Courier New">()<br>3、<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/Socket.html#isConnected()"><strong><u><font color=#800080>isConnected</font></u></strong></a>()<br>发现前两个都没用，即使已经断开了，返回的还是false，只有第三个可以解决问题。<br>具体原因未知。<br><br>2007-4-19更新：<br>第三个也解决不了问题，还会出现同样的异常，目前的解决方法是catch SocketException，不管socket的状态如何，都把它关闭了重新再连，但是SocketException的种类有很多，不一定是因为Socket已关闭，所以这种方法有点粗鲁，但找不到更好的方法。</font></p>
<img src ="http://www.blogjava.net/amplifier/aggbug/110131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-04-12 12:21 <a href="http://www.blogjava.net/amplifier/archive/2007/04/12/110131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java控制台程序如何在用户关闭时执行清理代码</title><link>http://www.blogjava.net/amplifier/archive/2007/04/12/110085.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 12 Apr 2007 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/04/12/110085.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/110085.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/04/12/110085.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/110085.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/110085.html</trackback:ping><description><![CDATA[通过<br>Runtime.getRuntime().<strong>addShutdownHook</strong>(<font color=#0000ff>Thread</font>&nbsp;hook)<br>方法可以给当前的进程注册一个清理线程，当进程退出的时候，会执行线程中的代码。<br><br>1、为了统一清理线程的实现，可以做一个Destroyable接口，实现此接口的类都有一个destroy()方法，里面包含了该类的清理过程，例如关闭数据库连接、关闭Socket连接等。<br>Destroyable接口的代码：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee" twffan="done"><span style="COLOR: #008080" twffan="done">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff" twffan="done">package</span><span style="COLOR: #000000" twffan="done">&nbsp;net.blogjava.amplifier;<br></span><span style="COLOR: #008080" twffan="done">&nbsp;2</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">&nbsp;3</span>&nbsp;<span style="COLOR: #000000" twffan="done"></span><span style="COLOR: #008000" twffan="done">/**</span><span style="COLOR: #008000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">&nbsp;4</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;建立此接口的目的是为了实现程序退出时的清理<br></span><span style="COLOR: #008080" twffan="done">&nbsp;5</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;在Java控制台程序中，用户可以通过关闭命令行窗口或按下Ctrl+C来结束程序的运行<br></span><span style="COLOR: #008080" twffan="done">&nbsp;6</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;这时候应该保证资源能够被正确释放，例如数据库的连接、Socket的连接应该关闭<br></span><span style="COLOR: #008080" twffan="done">&nbsp;7</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;实现了本接口的类的实例引用可以由一个ShutdownHook线程来操作<br></span><span style="COLOR: #008080" twffan="done">&nbsp;8</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;此线程在虚拟机退出时执行，详见Runtime.addShutdownHook()方法<br></span><span style="COLOR: #008080" twffan="done">&nbsp;9</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*&nbsp;</span><span style="COLOR: #808080" twffan="done">@author</span><span style="COLOR: #008000" twffan="done">&nbsp;amplifier<br></span><span style="COLOR: #008080" twffan="done">10</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;*<br></span><span style="COLOR: #008080" twffan="done">11</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;</span><span style="COLOR: #008000" twffan="done">*/</span><span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">12</span>&nbsp;<span style="COLOR: #000000" twffan="done"></span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">interface</span><span style="COLOR: #000000" twffan="done">&nbsp;Destroyable&nbsp;{<br></span><span style="COLOR: #008080" twffan="done">13</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000" twffan="done">/**</span><span style="COLOR: #008000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">14</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;实现本接口的类需要实现此方法，方法中包含该类的清理代码，<br></span><span style="COLOR: #008080" twffan="done">15</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;例如关闭数据库连接、关闭Socket连接等<br></span><span style="COLOR: #008080" twffan="done">16</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br></span><span style="COLOR: #008080" twffan="done">17</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000" twffan="done">*/</span><span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">18</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">void</span><span style="COLOR: #000000" twffan="done">&nbsp;destroy();<br></span><span style="COLOR: #008080" twffan="done">19</span>&nbsp;<span style="COLOR: #000000" twffan="done">}</span></div>
<br>2、建立一个继承于Thread的类ShutdownHook，里面的一个域是Destroyable实现类的引用，在该类的构造函数中可以传入该Destroyable实现类。<br>ShutdownHook的代码：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee" twffan="done"><span style="COLOR: #008080" twffan="done">&nbsp;1</span>&nbsp;<span style="COLOR: #0000ff" twffan="done">package</span><span style="COLOR: #000000" twffan="done">&nbsp;net.blogjava.amplifier;<br></span><span style="COLOR: #008080" twffan="done">&nbsp;2</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">&nbsp;3</span>&nbsp;<span style="COLOR: #000000" twffan="done"></span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">class</span><span style="COLOR: #000000" twffan="done">&nbsp;ShutdownHook&nbsp;</span><span style="COLOR: #0000ff" twffan="done">extends</span><span style="COLOR: #000000" twffan="done">&nbsp;Thread&nbsp;{<br></span><span style="COLOR: #008080" twffan="done">&nbsp;4</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">&nbsp;5</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">private</span><span style="COLOR: #000000" twffan="done">&nbsp;Destroyable&nbsp;desObj;<br></span><span style="COLOR: #008080" twffan="done">&nbsp;6</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080" twffan="done">&nbsp;7</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;ShutdownHook(Destroyable&nbsp;desObj){<br></span><span style="COLOR: #008080" twffan="done">&nbsp;8</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">this</span><span style="COLOR: #000000" twffan="done">.desObj&nbsp;</span><span style="COLOR: #000000" twffan="done">=</span><span style="COLOR: #000000" twffan="done">&nbsp;desObj;<br></span><span style="COLOR: #008080" twffan="done">&nbsp;9</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">10</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080" twffan="done">11</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;@Override<br></span><span style="COLOR: #008080" twffan="done">12</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">void</span><span style="COLOR: #000000" twffan="done">&nbsp;run()&nbsp;{<br></span><span style="COLOR: #008080" twffan="done">13</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">if</span><span style="COLOR: #000000" twffan="done">(</span><span style="COLOR: #0000ff" twffan="done">this</span><span style="COLOR: #000000" twffan="done">.desObj</span><span style="COLOR: #000000" twffan="done">!=</span><span style="COLOR: #0000ff" twffan="done">null</span><span style="COLOR: #000000" twffan="done">){<br></span><span style="COLOR: #008080" twffan="done">14</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">try</span><span style="COLOR: #000000" twffan="done">{<br></span><span style="COLOR: #008080" twffan="done">15</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">this</span><span style="COLOR: #000000" twffan="done">.desObj.destroy();<br></span><span style="COLOR: #008080" twffan="done">16</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">17</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">catch</span><span style="COLOR: #000000" twffan="done">&nbsp;(Exception&nbsp;e)&nbsp;{<br></span><span style="COLOR: #008080" twffan="done">18</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">19</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">20</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">21</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">22</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000" twffan="done">/**</span><span style="COLOR: #008000" twffan="done">&nbsp;</span><span style="COLOR: #008000" twffan="done">*//**</span><span style="COLOR: #008000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">23</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="COLOR: #808080" twffan="done">@param</span><span style="COLOR: #008000" twffan="done">&nbsp;args<br></span><span style="COLOR: #008080" twffan="done">24</span>&nbsp;<span style="COLOR: #008000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000" twffan="done">*/</span><span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">25</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">static</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">void</span><span style="COLOR: #000000" twffan="done">&nbsp;main(String[]&nbsp;args)&nbsp;{<br></span><span style="COLOR: #008080" twffan="done">26</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080" twffan="done">27</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">28</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">29</span>&nbsp;<span style="COLOR: #000000" twffan="done"><br></span><span style="COLOR: #008080" twffan="done">30</span>&nbsp;<span style="COLOR: #000000" twffan="done">}</span></div>
<br>3、在main()方法中注册ShutdownHook。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee" twffan="done"><span style="COLOR: #008080" twffan="done">&nbsp;1</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">static</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">void</span><span style="COLOR: #000000" twffan="done">&nbsp;main(String[]&nbsp;args){<br></span><span style="COLOR: #008080" twffan="done">&nbsp;2</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DestroyableImpl&nbsp;di&nbsp;</span><span style="COLOR: #000000" twffan="done">=</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">new</span><span style="COLOR: #000000" twffan="done">&nbsp;DestroyableImpl();<br></span><span style="COLOR: #008080" twffan="done">&nbsp;3</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShutdownHook&nbsp;sh&nbsp;</span><span style="COLOR: #000000" twffan="done">=</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">new</span><span style="COLOR: #000000" twffan="done">&nbsp;ShutdownHook(di);<br></span><span style="COLOR: #008080" twffan="done">&nbsp;4</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.getRuntime().addShutdownHook(sh);<br></span><span style="COLOR: #008080" twffan="done">&nbsp;5</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.getRuntime().addShutdownHook(</span><span style="COLOR: #0000ff" twffan="done">new</span><span style="COLOR: #000000" twffan="done">&nbsp;Thread(){<br></span><span style="COLOR: #008080" twffan="done">&nbsp;6</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff" twffan="done">public</span><span style="COLOR: #000000" twffan="done">&nbsp;</span><span style="COLOR: #0000ff" twffan="done">void</span><span style="COLOR: #000000" twffan="done">&nbsp;run(){<br></span><span style="COLOR: #008080" twffan="done">&nbsp;7</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000" twffan="done">"</span><span style="COLOR: #000000" twffan="done">正在退出&#8230;&#8230;</span><span style="COLOR: #000000" twffan="done">"</span><span style="COLOR: #000000" twffan="done">);<br></span><span style="COLOR: #008080" twffan="done">&nbsp;8</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080" twffan="done">&nbsp;9</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br></span><span style="COLOR: #008080" twffan="done">10</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;di.otherMethod();<br></span><span style="COLOR: #008080" twffan="done">11</span>&nbsp;<span style="COLOR: #000000" twffan="done">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<img src ="http://www.blogjava.net/amplifier/aggbug/110085.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-04-12 10:08 <a href="http://www.blogjava.net/amplifier/archive/2007/04/12/110085.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何让部署在Tomcat的某个应用在Tomcat启动时自动启动</title><link>http://www.blogjava.net/amplifier/archive/2007/03/19/104827.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Mon, 19 Mar 2007 13:59:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/03/19/104827.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/104827.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/03/19/104827.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/104827.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/104827.html</trackback:ping><description><![CDATA[在Tomcat 5.5.20里，把一个war包丢在Tomcat的webapps目录下，启动Tomcat后并不会自动启动那个应用，需要进入Tomcat manager，手动启动那个应用。为了实现应用的自动启动，需要在Tomcat的conf/server.xml里的 
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">Host</span><span style="COLOR: #0000ff">&gt;&lt;/</span><span style="COLOR: #800000">Host</span><span style="COLOR: #0000ff">&gt;</span></div>之间加入一个<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">Context </span><span style="COLOR: #ff0000">docBase</span><span style="COLOR: #0000ff">="应用的根"</span><span style="COLOR: #ff0000"> path</span><span style="COLOR: #0000ff">="应用程序相对webapps的目录"</span><span style="COLOR: #ff0000"> reloadable</span><span style="COLOR: #0000ff">="当配置修改时是否需要自动重新加载，是则为true，否则为false"</span><span style="COLOR: #0000ff">&gt;&lt;/</span><span style="COLOR: #800000">Context</span><span style="COLOR: #0000ff">&gt;</span></div><br />特此备忘！<img src ="http://www.blogjava.net/amplifier/aggbug/104827.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-03-19 21:59 <a href="http://www.blogjava.net/amplifier/archive/2007/03/19/104827.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BIRT初体验</title><link>http://www.blogjava.net/amplifier/archive/2007/01/09/92738.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Tue, 09 Jan 2007 12:55:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2007/01/09/92738.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/92738.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2007/01/09/92738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/92738.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/92738.html</trackback:ping><description><![CDATA[从来没做过报表，突然要用到，急忙之中想起了Eclipse里面有个报表插件，上eclipse.org查看，知道它叫BIRT。下载，安装，不能运行，但在about里面看到这个插件已加载。再回官方网站一看，原来还需要EMF,GEF，依次下回来装上，可以用了。打开帮助里的指南，一步一步做了个表格式的报表，感觉还是比较简单的。但我的目标是要做图形报表，并且可以程序控制。研究了两天，有了初步的了解，做出了一个简单的柱状图，也能接受一些参数了，但程序控制还没头绪，也不知道从何处入手，文档里面只有API，没有使用说明，也没有找到相关的书籍。<br />记录下一些东西：<br />1、BIRT需要下载iText才能生成PDF报表，而且iText的版本必须跟网站上的要求严格一致，例如要求1.3的不能用1.3.1的，因为插件配置文件里写明是iText-1.3.jar，如果下了1.3.1版本的，也必须把文件名改成1.3才行。同时还需要iTextAsian.jar。<br />2、BIRT支持Web查看。其实在Eclipse里面预览就是通过本地web服务器查看的。可以把报表发布到tomcat里。<br />3、BIRT支持参数化报表，可以根据用户的输入生成相应的报表，但并不是什么地方都可以用参数，还是要编程才能保证灵活性。例如SQL查询里不支持表名作为参数（其实是数据库本身不支持）。图里的标题也不能用参数。<br />4、图形里的日期格式化不够灵活，还需要编程的支持。<br /><br />还要研究一下怎样通过程序控制报表的生成。<br /><br />本文为个人备忘录。<img src ="http://www.blogjava.net/amplifier/aggbug/92738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2007-01-09 20:55 <a href="http://www.blogjava.net/amplifier/archive/2007/01/09/92738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse启动参数解决占用CPU 100%，必须“立即结束”的问题</title><link>http://www.blogjava.net/amplifier/archive/2006/11/02/78619.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 02 Nov 2006 03:02:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/11/02/78619.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/78619.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/11/02/78619.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/78619.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/78619.html</trackback:ping><description><![CDATA[机器配置：<br />P4 2.8 GHz 超线程，内存 1G<br /><br />症状：<br />使用Eclipse时，点击某个按钮或图标甚至正在输入代码时，整个程序突然失去响应，菜单栏变白，除了关闭按钮，其他地方都没反应，在任务管理器中发现javaw.exe占用CPU50%（相当于单CPU100%），内存占用200多M，且CPU和内存占用数值均停止不动，机器风扇开始轰鸣，再等半天还是这个样子。点击“关闭”按钮出现“立即结束”对话框，只能很无奈地强行退出，有时一天碰到10多次，基本失去可用性。<br /><br />寻找解决方案：<br />百度、google搜索，一般的解决方案是，调整启动参数-Xms -Xmx，增大堆内存，然而，在上述机器上设置为-Xms512m -Xmx512m，仍然没效，到失去响应的时候占用的内存依然是200多M。<br />看来这个问题需要自己解决了。用命令行方式启动eclipse：<br />java -Xms512m -Xmx512m -jar startup.jar<br />到失去响应的时候，发现命令行里打印出java.lang.OutOfMemoryError: PermGen space，打开workspace/.metadata/.log文件，发现很多这样的字符串，把这段话贴到搜索引擎上，发现很多这种问题，不过一般出现在Tomcat，Weblogic等Web应用程序上，没有人报告过会出现在Eclipse上。解决方案是增加启动参数：<br />-XX:MaxNewSize=256m -XX:MaxPermSize=256m<br />于是在eclipse.ini里把启动参数改为：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Xms512m </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">Xmx512m </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">XX:MaxNewSize</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">256m </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">XX:MaxPermSize</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">256m</span></div><br />启动Eclipse，用了几天，都没再出现失去响应的症状。<br /><br />关于MaxPermSize的文章：<br /><a href="http://www.sumoc.com/blog/index.cfm?mode=entry&amp;entry=CDCDBF8B-5004-2066-B7460CDEAB79328F" target="_blank">CFMX JVM Tuning - The difference between MaxPermSize and Heap Size</a><img src ="http://www.blogjava.net/amplifier/aggbug/78619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-11-02 11:02 <a href="http://www.blogjava.net/amplifier/archive/2006/11/02/78619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过Socket发送Unicode不可打印字符</title><link>http://www.blogjava.net/amplifier/archive/2006/11/02/78613.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Thu, 02 Nov 2006 02:39:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/11/02/78613.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/78613.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/11/02/78613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/78613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/78613.html</trackback:ping><description><![CDATA[很遗憾，刚才写了很多，一按“代码”按钮，没有弹出对话框，但整个浏览器已经不能动，再按一下Alt+F4，整个浏览器关闭，什么都没有了，哭……我用的是TheWorld1.33+IE7。<br /><br />刚才的大意是：<br />利用socket发送字符串时，为了区分字符串的起始、结束与中间各个部分的间隔，需要一些特殊字符作为分隔符，但普通可打印字符有可能出现在要发送的字符串中，不能作为分隔符，所以只能使用不可打印字符。Java使用的是Unicode编码，可通过\uxxxx来表示编码为xxxx的字符。例如：\u0129,\u0130,\u0131都是不可打印字符。但是，通过socket发送和接收字符串时，需要指定编码，否则会使用操作系统的默认编码。在发送端，通过OutputStream的write()函数写出要发送的字符串的Bytes，这些bytes要通过String.getBytes(编码名称)来获得，例如编码名称为: UTF-16BE，则：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <span style="COLOR: #000000">socket.getOutputStream.write(str.getBytes(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UTF-16BE</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));</span></div><br />读socket的时候，通过InputStreamReader的read()函数来一个个字符地读取，这时候如果不指定编码，使用的也是操作系统的默认编码，例如中文的GB18030，这时候有些Unicode字符没有对应的GB18030编码，读出来的就都是?号。所以必须在InputStreamReader的构造函数中指定字符编码，例如：<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <span style="COLOR: #000000">InputStreamReader isr </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> InputStreamReader(socket.getInputStream(),</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UTF-16BE</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000"> c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">  (</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">)isr.read();</span></div><img src ="http://www.blogjava.net/amplifier/aggbug/78613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-11-02 10:39 <a href="http://www.blogjava.net/amplifier/archive/2006/11/02/78613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短信平台开发笔记 4 （多线程） </title><link>http://www.blogjava.net/amplifier/archive/2006/10/25/77242.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Wed, 25 Oct 2006 09:34:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/10/25/77242.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/77242.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/10/25/77242.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/77242.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/77242.html</trackback:ping><description><![CDATA[改了一下实现，采用“生产者-消费者”模式。每个串口一个线程，读取BlockingQueue里的待发信息，作为消费者，发送完毕后把发送结果写到另外一个BlockingQueue里；查询线程定时查询数据库，获得待发信息并加入到BlockingQueue里；结果更新线程读取BlockingQueue里的短信发送结果，更新到数据库里，并把结果发送到客户端。<br />这样会带来一个问题，发送线程发送短信需要一定的时间，可能某条待发信息已经在队列里了，但查询线程并不知道，继续把该信息入列，所以发送线程在发送某条短信前要检查数据库，看是否已经发送过，如果发送过，则不再发送。<img src ="http://www.blogjava.net/amplifier/aggbug/77242.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-10-25 17:34 <a href="http://www.blogjava.net/amplifier/archive/2006/10/25/77242.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短信平台开发笔记 3 （图形界面）</title><link>http://www.blogjava.net/amplifier/archive/2006/10/21/76538.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Sat, 21 Oct 2006 06:42:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/10/21/76538.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/76538.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/10/21/76538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/76538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/76538.html</trackback:ping><description><![CDATA[
		<p>做好核心部分，只完成了一半，剩下的图形界面设计还需要一个漫长的过程。<br />SWT做图形界面是个繁琐的过程，虽然可以用VE、SWT Designer帮助布局，设置一些属性，添加一些事件，但里面的逻辑却是要自己先想好。<br />以“设置”页面为例，为了设置各模块的参数，需要考虑很多问题：<br />1、哪些是立即生效，哪些是重启才能生效？<br />2、什么时候哪个widget需要被Disable，什么时候需要被Enable？<br />3、怎么验证用户输入的东西是符合逻辑的？<br />……<br />还需要把图形界面、确定前的临时配置类、内存中的配置类、硬盘上的配置文件结合起来，什么时候给哪个赋值，什么时候从哪个获得值都要考虑清楚，同时，在程序运行过程中还需要不断读取内存中的配置类，获得运行时参数，必须保证线程之间不发生冲突。</p>
<img src ="http://www.blogjava.net/amplifier/aggbug/76538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-10-21 14:42 <a href="http://www.blogjava.net/amplifier/archive/2006/10/21/76538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短信平台开发笔记 2 （MMS相关材料）</title><link>http://www.blogjava.net/amplifier/archive/2006/10/09/74036.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Mon, 09 Oct 2006 04:26:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/10/09/74036.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/74036.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/10/09/74036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/74036.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/74036.html</trackback:ping><description><![CDATA[支持GPRS的MODEM可以连上互联网，就能支持MMS（彩信）的发送，但实际上MMS的机制与SMS相差很大，并不是几个AT指令就能搞定的。而且MMS没有统一的标准，各个厂家的规格有所不同，运营商使用的标准也不同。<br />怎样才能像发短信一样通过串口连接MODEM发送彩信？似乎还没有相关的解决方案，现有的都是整套的软件。<br /><a href="http://blog.csdn.net/sealedxlmg/archive/2005/01/01/237054.aspx">http://blog.csdn.net/sealedxlmg/archive/2005/01/01/237054.aspx</a><img src ="http://www.blogjava.net/amplifier/aggbug/74036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-10-09 12:26 <a href="http://www.blogjava.net/amplifier/archive/2006/10/09/74036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短信平台开发笔记 1</title><link>http://www.blogjava.net/amplifier/archive/2006/10/09/73927.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Sun, 08 Oct 2006 16:12:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/10/09/73927.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/73927.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/10/09/73927.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/73927.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/73927.html</trackback:ping><description><![CDATA[
		<p>Modem型号：Wavecom Fastrack M1206B，支持GPRS，详细文档地址<a href="http://www.wavecom.com/modules/movie/scenes/search/index.php?fuseAction=searchPopup&amp;article_identity=WMPuSupportHardFirmwaresM1206B&amp;rubric_identity=WMPuSupportHardFirmwares&amp;part=long">http://www.wavecom.com/modules/movie/scenes/search/index.php?fuseAction=searchPopup&amp;article_identity=WMPuSupportHardFirmwaresM1206B&amp;rubric_identity=WMPuSupportHardFirmwares&amp;part=long</a><br /><br />短信存储器：SM（普通短信），SR（信息报告），移动动感地带各20条，联通UP新势力各100条<br /><br />串口速率：有的只能工作在9600bps，有的可以工作在多种速率<br /></p>
<img src ="http://www.blogjava.net/amplifier/aggbug/73927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-10-09 00:12 <a href="http://www.blogjava.net/amplifier/archive/2006/10/09/73927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让老手机变成短信平台-AT指令的应用</title><link>http://www.blogjava.net/amplifier/archive/2006/05/19/46967.html</link><dc:creator>amp@java</dc:creator><author>amp@java</author><pubDate>Fri, 19 May 2006 01:28:00 GMT</pubDate><guid>http://www.blogjava.net/amplifier/archive/2006/05/19/46967.html</guid><wfw:comment>http://www.blogjava.net/amplifier/comments/46967.html</wfw:comment><comments>http://www.blogjava.net/amplifier/archive/2006/05/19/46967.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/amplifier/comments/commentRss/46967.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/amplifier/services/trackbacks/46967.html</trackback:ping><description><![CDATA[<p>以NOKIA8250为例。通过8250的红外与PC连接之后，会产生一个虚拟串口，这个串口的序号可能在每台电脑上都不一样。利用这个串口，就可以对手机进行一系列操作，包括发送、接收短信。通过程序操作串口，就可以把这部手机做成短信平台。<br />
在Windows中，打开超级终端，在手机未连接之前，查看连接可使用的串口列表，然后连接手机，再查看列表，多出来的那个串口就是与手机通信的串口。通过该串口连接手机，就可以用AT指令来操作它。<br />
输入AT回车，出现OK，就说明这个串口是支持AT指令的，有可能是手机，也有可能是普通的MODEM。<br />
输入AT+CGMI回车，出现手机厂商信息，例如NOKIA，就说明这是手机，下面就可以进行一系列的操作了。<br />
AT指令有几个实用的规则：<br />
1.输入AT指令然后加&#8220;?&#8221;，就能列出该指令的当前状态，例如输入AT+CSCS?，就能列出当前手机使用的字符集，例如：+CSCS: "PCCP437"。<br />
2.输入AT指令然后加&#8220;=?&#8221;，就能列出该指令的可选值，也就是手机所能支持的所有值，例如输入AT+CSCS=?，就能列出手机能支持的所有字符集，例如：+CSCS: ("GSM","HEX","IRA","PCCP437","PCDN","8859-1")，可以通过AT+CSCS="HEX"来设置手机的字符集为HEX。<br />
<br />
<br />
短信内容的格式有两种，一种是text，一种是PDU，text格式比较简单，但不能发送特殊的短信，例如免提短信，发送中文短信也会乱码。PDU格式则可以发送各种形式（免提，闪烁）和字符集的短信，不过PDU不够直观，需要通过程序来编码解码，例如发送到8613000000000的短信&#8220;中文信息&#8221;的PDU编码为：0011000D91683100000000F00008A70C4E2D65874FE1606F000D000A，其长度为27。在PDU格式下，短信内容还包含了目标号码，而在text格式下，目标号码和短信内容是分开的。<a href="http://www.baidu.com/s?wd=%C8%F1%B7%BD%B3%AC%BC%B6SMS%BF%D8%BC%FE&amp;cl=3">锐方超级SMS控件</a>是一个很好的PDU编解码控件。<br />
<br />
与短信相关的AT指令：<br />
</p>
<table border="1" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td width="11%">AT 指令</td>
            <td width="89%">功 能 </td>
        </tr>
        <tr>
            <td width="11%">AT+CMGC</td>
            <td width="89%">Send an SMS command（发出一条短消息命令）</td>
        </tr>
        <tr>
            <td width="11%">AT+CMGD</td>
            <td width="89%">Delete SMS message（删除SIM卡内存的短消息） </td>
        </tr>
        <tr>
            <td width="11%">AT+CMGF</td>
            <td width="89%">Select SMS message formate（选择短消息信息格式：0-PDU;1-文本）</td>
        </tr>
        <tr>
            <td width="11%">AT+CMGL</td>
            <td width="89%">List SMS message from preferred store（列出SIM卡中的短消息，在PDU模式下，该值为数字，在text模式下，该值为字符串。PDU/text：0/"REC UNREAD"-未读，1/"REC READ"-已读，2/"STO UNSENT"-待发，3/"STO SENT"-已发，4/"ALL"-全部的）</td>
        </tr>
        <tr>
            <td width="11%">AT+CMGR</td>
            <td width="89%">Read SMS message（读短消息）</td>
        </tr>
        <tr>
            <td width="11%">AT+CMGS</td>
            <td width="89%">Send SMS message（发送短消息。在PDU格式下，该值设置为PDU长度，例如30；在Text格式下，该值设置为目标手机号码字符串，例如"8613888888888"。注意，在PDU模式下，手机号码需要加上86开头，否则不能发送。） </td>
        </tr>
        <tr>
            <td width="11%">AT+CMGW</td>
            <td width="89%">Write SMS message to memory（向SIM内存中写入待发的短消息）</td>
        </tr>
        <tr>
            <td width="11%">AT+CMSS</td>
            <td width="89%">Send SMS message from storage（从SIN|M内存中发送短消息） </td>
        </tr>
        <tr>
            <td width="11%">AT+CNMI</td>
            <td width="89%">New SMS message indications（设置是否显示新收到的短信，一般设成2,1,0,0,0，手机收到新的短信后会给PC发一条消息，包含了该短信在内存中的索引号，通过该索引号就可以读出该短信）</td>
        </tr>
        <tr>
            <td width="11%">AT+CPMS</td>
            <td width="89%">Preferred SMS message storage（选择短消息内存）</td>
        </tr>
        <tr>
            <td width="11%">AT+CSCA </td>
            <td width="89%">SMS service center address（短消息中心地址）</td>
        </tr>
        <tr>
            <td width="11%">AT+CSCB</td>
            <td width="89%">Select cell broadcast messages（选择蜂窝广播消息） </td>
        </tr>
        <tr>
            <td width="11%">AT+CSMP</td>
            <td width="89%">Set SMS text mode parameters（设置短消息文本模式参数） </td>
        </tr>
        <tr>
            <td width="11%">AT+CSMS</td>
            <td width="89%">Select Message Service（选择短消息服务）</td>
        </tr>
    </tbody>
</table>
<br />
知道这些之后，就可以通过编程来操作手机。在java中，利用Java Communication包可以操作串口，但官方的包在3.0之后就支持Linux和Solaris平台了，Windows平台的只支持到2.0，98年出的，不过在XP下还能使用，google一下就可以下载到，例如：<a href="http://mdubuc.freeshell.org/Jolt/javacomm20-win32.zip">http://mdubuc.freeshell.org/Jolt/javacomm20-win32.zip</a>。也可以用开源的<a href="http://www.frii.com/%7Ejarvi/rxtx">Rxtx</a>实现串口通信。<br />
如果不想直接操作AT指令，还可以使用开源的<a href="http://smslib.org/">SMSLib</a>包，该包封装了与短信相关的所有AT指令，也实现了PDU编解码功能，使用起来十分方便。 
<img src ="http://www.blogjava.net/amplifier/aggbug/46967.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/amplifier/" target="_blank">amp@java</a> 2006-05-19 09:28 <a href="http://www.blogjava.net/amplifier/archive/2006/05/19/46967.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>