1、NAME:一個目錄或文件的名字,不包含URL模式及全部路徑。
例如:"<directory>/"注意必須要有斜線
"<filename.extension>"有後綴名的文件
"<filename>"沒有後綴名的文件
2、PATH:一個目錄或文件的路徑。
例如:/<root>/<directory>/
3、URL:一個文件或目錄的URL。
例如:file://<host>/<root>/<directory>/<filename.ex>
file://<host>/<root>/<directory>/<directoryname>/
----------------------------------------------------------------------------------------------------------------
最近由於開發需要,研究了一下J2ME的文件系統操作(JSR75),對常用操作進行了一下總結。
(1)判斷 手機是否支持文件系統
/**
* 檢測手機是否支持文件系統
* @return
*/
public boolean isSupportFileSystem(){
String v = System
.getProperty("microedition.io.file.FileConnection.version");
if(v!=null)return true;
return false;
}
通過判斷System的Property是否存在來判斷。
(2)打開文件連接
無論是要讀文件還是要寫文件,首先必須得到該文件的Connection。
使用Connector.open方法,有2個參數,第一個參數是路徑,第二個參數是權限。
權限沒什麼好說的了,一共就3個可能:Connector.READ、Connector.WRITE、Connector.READ_WRITE。
現在來說說路徑,路徑是以URL形式書寫的,以"file://"開頭,如果是本機上的文件就加上localhost,即如果是E:/a.dat文件的路徑應該是"file://localhost/E:/a.dat"。
順便說說手機的目錄結果,由於我是使用S60第3版的機器進行測試,所以介紹一下其目錄結構。KJava程序可訪問的驅動器就2個:C和E(如果有擴展卡)。E驅動器下所有目錄文件都可以訪問,路徑是E:/開始;C驅動則不是,只有圖片、聲音和影像三個目錄可以訪問,訪問其它目錄將拋SecurityException,其這三個目錄的路徑分別是C:/data/Images、C:/data/Sounds、C:/data/Videos。怎麼知道有哪些目錄可以訪問呢,很簡單把WTK自帶的PDADemo放在手機上,運行FileBrowser測試一下就行了。
FileConnection fc = (FileConnection)
Connector.open(file://localhost/E:/a.dat , Connector_READ_WRITE);
(3)讀文件
InputStream fis = fc.openInputStream();
很簡單,就是用openInputStream打開一個流,和讀取網絡數據一樣,這裏就不贅述了。
(4)寫文件
byte[] b="Hello World".getBytes();
OutputStream fos = fc.openOutputStream();
fos.write(b,0,b.length);
使用方法也是和寫網絡數據一樣,打開一個OutputStream就可以了,不過有一點要注意的(在N93上測試的結果,其它機器不清楚),寫文件總是從開頭開始寫,而且不會清空原來的內容。例如本來文件中有內容abcdefghijk,再打開文件往裏面寫入123,最後文件的內容是什麼呢?不是abcdefghijk123,也不是123,而是123defghijk。那麼需要續寫文件怎麼辦?我的做法的先把原內容讀出到一個StringBuffer中,再續寫在StringBuffer裏,再寫入文件,不知道還有沒有更方便的方法。
----------------------------------------------------------------------------------------------------------------
前言:在網上搜了一圈,沒有找到多少PIM和FC的中文資料,所以,參考了一些資料,並簡單寫下一些我使用中的想法,希望能和大家多多交流,不足之處,請大家不吝賜教,我的郵箱是:[email protected]
概述
JSR 75(PDA Optional Packages for the J2METM Platform)中定義了兩個可選包:
PIM (The Personal Information Management)API,提供對個人信息數據的訪問,一般包括名片夾,日曆項,和待辦事項。
FC(The FileConnection) APIs,提供對本地文件系統的訪問。
本文簡單講解FC API的特性的用法。
一、FC API與RMS
簡單地寫一點,這兩個東東其實沒有可比性,功能側重不同,FC APIs提供了MIDlets與本地文件和其它應用的交互,比如我們可以通過FC API在MIDlets中打開外部的各種文件,並且保存一些極大的資源,這一點RMS沒有辦法做到的,FC API並不是強制實現的。
RMS用來存儲程序中的一些數據,FC API不會取代RMS。
二、FC API簡介
1.FC API中的類和接口
接口:
Javax.microedition.io.file.FileConnection,繼承自CLDC中的javax.microedition.StreamConnection;
javax.microedition.io.file.FIleSystemListener,用於監聽文件系統目錄狀態變化的通知,比如文件的刪除和新增,存儲卡的撥出的插入;onnectionClosed
類:
javax.microedition.io.file.FileSystemRegistry,用於獲取當前所有文件的根目錄和管理跟蹤文件系統的監聽器;
javax.microedition.io.file.IllegalModeException,文件打開模式異常,當試圖寫入以只讀方式打開的文件時,該異常會被拋出;
javax.microedition.io.file.ConnectionClosedException,當試圖對一個已經關閉的FileConnection對像作操作時,該異常會被拋出。
2.驗證系統是否支持FC API
可以通過系統屬性來驗證手機是否支持FC API:
System.getProperty("microedition.io.file.FileConnection.version");
如果支持的話,會返回FC API的版本號,一般是1.0,
如果不支持,則返回null,
現在支持FC API的手機非常少,
MOTO的A1系列手機有幾款支持,我手上用過的V635就支持。
(說明一下,MOTO用的是自己的包com.motorola.io.file,但和FC幾乎一樣)
三、FC API的使用
1.打開一個文件
將使用file協議的url傳入Connector以創建FileConnection類,可以以READ,READ_WRITE和WRITE三種方式打開,代碼如下:
FileConnection fconn = null;
try{
fconn = (FileConnection)Connector.open("file:///a/mobile/audio/playlist.txt",Connector.READ);
}
catch(Exception e){
log("open file error:"+e); //大家當成System.out.println()就好
}
值得注意的是,如果文件不存在的話,語句也可以正常執行,並不會拋出任何異常,所以,爲了避免後續操作中不必要的麻煩,我們要用fconn.exists()方法來自己判斷文件是否存在:
FileConnection fconn = null;
try{
fconn = (FileConnection)Connector.open("file:///a/mobile/audio/playlist.txt",Connector.READ);
if(fconn.exist()){
//..........................
}
else{//..................................}
}
catch(Exception e){
log("open file error:"+e);
}
2.對文件的讀寫操作
讀文件:
通過InputStream從FileConnection讀取,然後自己再對InputStream做解析,用法很簡單,和讀取HttpConnection差不多,附上以前程序裏的一段詳細代碼,是用來讀取播放列表文件的,程序中爲了方便,是使用DataInputStream直接讀的,沒有用到InputStream,實際上原理是一樣的:
private void loadLists(){
log("try open playlist");
musicList.removeAllElements();//musicList是一個Vector,在本段代碼之外定義並初始化
FileConnection fconn = null;
DataInputStream dis = null;
try{
//以只讀模式打開playlist.txt文件
fconn = (FileConnection)Connector.open("file:///a/mobile/audio/playlist.txt",Connector.READ);
dis=fconn.openDataInputStream();//開輸入流
String tmp=null;
do{
try{
tmp=dis.readUTF();//讀文件路徑
} catch(Exception e){
tmp = null;
}
if(tmp != null){
OneMusic onemusic=new OneMusic();
onemusic.filepath=tmp;
onemusic.filename=dis.readUTF();//讀文件名
onemusic.filesize=dis.readLong();//讀文件大小
musicList.addElement(onemusic);
}
}while(tmp!=null);
log("playlist loaded");
dis.close();
fconn.close();
}
catch(Exception e){
e.printStackTrace();
}
}
寫文件:
通過OutputStream向FileConnection寫入,附上寫入播放列表的代碼,同樣我也用的是DataOutputStream,
private void saveLists(){
log("try save playlist");
FileConnection fconn = null;
DataOutputStream ous = null;
try{
//以讀寫模式打開
fconn = (FileConnection)Connector.open("file:///a/mobile/audio/playlist.txt",Connector.READ_WRITE);
if(!fconn.exists()){//判斷文件是否存在,如果不是,則新建一個
NpPlayer.instance.showlog.dealReportMsg("playlist not exists ,create");
fconn.create(); // create the file if it doesn't exist
log("playlist created!!");
} else {//如果文件存在,則將舊的文件刪除,建立一個新文件
fconn.delete();
log("playlist exists,delete");
fconn.create();
log("playlist created!!");
}
ous = fconn.openDataOutputStream() ;
log("saving playlists....");
for(int i=0;i<musicList.size();i++){//將音樂列表按路徑,文件名,文件大小的格式寫入播放列表文件中
OneMusic onemusic;
onemusic=(OneMusic)musicList.elementAt(i);
byte[] temp = null;
ByteArrayOutputStream bos =new ByteArrayOutputStream() ;
DataOutputStream dos =new DataOutputStream (bos) ;
dos.writeUTF(""+onemusic.filepath);
dos.writeUTF(""+onemusic.filename);
dos.writeLong(onemusic.filesize);
temp=bos.toByteArray();
dos.close();
bos.close();
ous.write(temp,0,temp.length);
}
ous.flush();
ous.close();
fconn.close();
log("playlist saved!!");
}
catch(Exception e){
e.printStackTrace();
}
finally {
try{
if (ous != null)
ous.close();
} catch (Exception closee){}
try{
if (fconn != null)
fconn.close();
} catch (Exception closee){}
}
}
3.對目錄的操作
判斷是文件還是目錄,使用isDirectory()方法
boolean isdir = fconn.isDirectory();
指定完整的路徑和目錄名後調用方法mkdir()來創建新的目錄:
FileConnection fconn = null;
try{
fconn = (FileConnection)Connector.open("file:///a/mobile/audio/mymusic",Connector.READ_WRITE);
fconn.mkdir();
}
catch(Exception e){}
列目錄下的所有內容,用list()方法,此方法返回一個java.util.Enumeration類的對像
java.util.Enumeration enu = fconn.list();
接下來就可以通過java.util.Enumeration中的hasMoreElements()方法來判斷目錄下是否還有內容並進行相應操作
while(enu.hasMoreElements()){
//.....................................
}
說明一點,此處返回的是一個java.util.Enumeration類的對像,實際上就是一個String數組,這一點參考FC API文檔:
public java.util.Enumeration list() throws java.io.IOException
Gets a list of all visible files and directories contained in a directory. The directory is the connection's target as specified in Connector.open().
Returns:
An Enumeration of strings, denoting the files and directories in the directory...................
...................................
所以,也可以使用這樣的方法:String[] tmp = fconn.list(),然後自己處理一下這個數組就行了。
4.監聽文件系統的變化
可以用FileSystemListener來監聽文件系統的改變(增加,刪除,修改),以便作出響應,
在此以存儲卡的撥出和插入爲例,代碼是找的現成的:)
public class FSListener implements FileSystemListener{
public void stateChanged(int state,String name){
if(state == FileSystemListener.ROOT_REMOVED)
//root removed
else if(state == FileSystemListener.ROOT_ADDED)
//root added
}
}
註冊監聽到FileSystemRegistry:
FileSystemListener listener = new FSListener();
FileSystemRegistry.addFileSystemListener(listener);
四、FC API的安全性
對於未經過簽名的MIDlet,在每次使用FC API讀取文件時,都會提示用戶是否允許,非常煩人
並且不允許對文件進行寫操作,,,
而MOTO自己的包更是狠,沒有認證的程序是不能讀取任何文件的。。。所以幾乎沒用如果程序中要用到FC API的話,最好還是去找產商認證一下,會大大提供程序的友好性。
----------------------------------------------------------------------------------------------------------------
這段時間因爲開發上要用到本地文件,因此開始接觸Jsr75的包,Jsr75分兩個部分,一部分是File,即本地文件系統,一部分是PIM,說白了就是電話本之類的信息,我先學習的是File部分,通過import javax.microedition.io.file.*裏的包,可以實現自由訪問本機的文件系統,就跟Windos裏的資源管理器一樣,在這裏我介紹幾個我寫的方法
一.獲取指定路徑的目錄和文件列表
/*目錄文件列表*/
public Vector list(String path)
{
try
{
FileConnection fc=(FileConnection)(Connector.open(path));
if(fc.exists())
{
Vector listVec=new Vector(0,1);
Enumeration en=fc.list();
while(en.hasMoreElements())
{
listVec.addElement((String)(en.nextElement()));
}
return listVec;
}
else
return null;
}
catch(Exception e)
{
System.out.println("listErr:"+e.toString());
return null;
}
}
方法裏的path參數就是要查找的路徑,比如file:///c:/pictures/,切記,如果是目錄Path,那麼後面的/一定不能省,否則會查找不到內容。這個方法返回的是一個包含了指定Path下的所有目錄名和文件名的向量。
二.建立或者保存一個文件到指定路徑
/*保存文件*/
public void saveFile(String path,byte[] fileData)
{
try
{
FileConnection fc=(FileConnection)(Connector.open(path));
fc.create();
fc.setWritable(true);
OutputStream os=fc.openOutputStream();
os.write(fileData);
os.close();
}
catch(Exception e)
{
System.out.println("saveFileErr:"+e.toString());
}
}
fileData是需要保存的文件內容,可以是聲音,也可以是圖像,或者文字之類
三.刪除指定文件
/*刪除文件*/
public void deleteFile(String path)
{
try
{
FileConnection fc=(FileConnection)(Connector.open(path));
if(fc.exists())
fc.delete();
}
catch(Exception e)
{
System.out.println("deleteFileErr:"+e.toString());
}
}
這個方法就不用多解釋了
四.讀取指定文件
/*讀取文件*/
public byte[] readFile(String path)
{
try
{
FileConnection fc=(FileConnection)(Connector.open(path));
if(fc.exists())
{
InputStream is=fc.openInputStream();
byte[] temp=new byte[is.available()];
is.read(temp);
is.close();
return temp;
}
else
return null;
}
catch(Exception e)
{
System.out.println("readFileErr:"+path+e.toString());
return null;
}
}
此方法也不用多解釋了。
以上是關於文件操作的最基本的一些功能,也是第一期的學習筆記研究到的內容,更多的內容,過幾天繼續研究繼續寫吧,呵呵。