jsr75相關知識總結

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;
  }
 }

此方法也不用多解釋了。

以上是關於文件操作的最基本的一些功能,也是第一期的學習筆記研究到的內容,更多的內容,過幾天繼續研究繼續寫吧,呵呵。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章