官术网_书友最值得收藏!

2.4 文件I/O

I/O即輸入與輸出,幾乎所有文件操作的工作都離不開I/O。對于Android游戲開發來說,I/O操作尤為重要,游戲中的地圖數據、人物圖片資源等的流暢讀取是保證游戲可玩性的重要方面。因此,在開發時,不同的場合必須選用合適的I/O操作方式,才能保證滿足用戶的需求。

Android中文件I/O分為3種方式:SD卡文件讀取、手機中文件夾的訪問和應用程序中assets文件的讀取,本節將結合簡單的小案例對這幾種文件I/O操作進行介紹。

2.4.1 訪問SD卡中的文件

伴隨著游戲品質的不斷提高,游戲數據占用的存儲空間也成幾何級數增加,以往幾十KB、幾MB的手機游戲已經發展為幾十MB、幾百MB甚至幾個GB的大型手機游戲。為了適應存儲需求的增長,SD卡也一直在進行更新換代,4GB、8GB、16GB大小的SD卡已隨處可見。

Android的設計者自然不會忽略這一點,在Android平臺上可以輕松地對手機SD卡中的文件進行讀取和操作。下面通過一個案例來詳細講解在Android開發中如何訪問SD卡中的文件。

1.案例的運行效果

運行本節案例Sample2_5,在輸入框中輸入要讀取的文件名,然后單擊“打開文件”按鈕。若SD卡中存在該文本文件,則在文本區域顯示出文件的內容,反之則提示沒有找到指定文件。本案例的運行效果如圖2-15和圖2-16所示。

▲圖2-15 成功加載SD卡中的文件

▲圖2-16 未找到指定的文件

提示

運行本案例時要注意SD卡中文本文件的編碼格式,在Android系統中一般要采用UTF-8編碼才能保證沒有亂碼出現。編碼格式為UTF-8的文本文件,見隨書中源代碼/第2章目錄下的AndroidIO.txt,讀者可以將該文件導入到手機或模擬器的SD卡中再對本案例進行測試。

2.案例的開發

介紹完本案例的運行效果以及文本文件編碼的注意事項后,接下來將對本案例的主控制類Sample2_5_Activity進行開發,其代碼如下。

代碼位置:見隨書中源代碼/第2章/Sample2_5/src/com/bn/pp5目錄下的Sample2_5_Activity.java。

      1       package  com/bn/pp5;
      2     import java.io.File;                                           //引入相關包
      3     public class Sample2_5_Activity extends Activity {        //創建Activity
      4            @Override
      5         public void onCreate(Bundle savedInstanceState) {      //重寫onCreate方法
      6                 super.onCreate(savedInstanceState);
      7             setContentView(R.layout.main);                        //跳轉到主界面
      8             Button ok=(Button)this.findViewById(R.id.Button01); //獲取打開按鈕的引用
      9             ok.setOnClickListener(                                 //為打開按鈕添加監聽器
      10                              new  OnClickListener(){
      11                              public  void  onClick(View  v)  {
      12                                      EditText  et1=(EditText)findViewById(R.id.EditText01);
      13                                      String  nr=loadText(et1.getText().toString().trim());
      14                                      EditText  et2=(EditText)findViewById(R.id.EditText02);
      15                            et2.setText(nr);                        //設置顯示框內容
      16                     }}); }
      17        public String loadText(String name){                     //加載SD卡文件方法
      18          String nr=null;                                           //內容字符串
      19             try{
      20                File f=new File("/sdcard/"+name);                //創建對應文件
      21                byte[] buff=new byte[(int) f.length()];         //創建響應大小的byte數組
      22                     FileInputStream  fis=new  FileInputStream(f);
      23                fis.read(buff);                                     //讀入文件
      24                fis.close();                                        //關閉輸入流
      25                nr=new String(buff, "utf-8");                      //轉碼生成字符串
      26                nr=nr.replaceAll("\\r\\n", "\n");                 //替換換行符
      27             }catch  (Exception  e)  {
      28                Toast.makeText(getBaseContext(),                 //Toast提示用戶
      29                                  "對不起,沒有找到指定文件。",
      30                                              Toast.LENGTH_LONG).show();
      31             }
      32          return nr;                                                 //返回內容字符串
      33     }}

? 第8-16行是為打開文件的按鈕添加監聽器,監聽器的功能為首先獲取文本框中用戶輸入的文件名,然后調用從SD卡加載文本文件的方法,獲取SD卡中的對應文件內容并送入EditText控件顯示。

? 第17-32行為加載SD卡中文本文件的方法,其入口參數為要加載文件的文件名。工作過程為首先用Java標準的I/O操作來加載指定文本文件中的數據,然后將數據編碼為字符串,并替換換行符等空白字符,最后返回加載的內容。

提示

通過上面的小案例可以看出,Android中對SD卡文件的I/O實現與標準Java相同,因此,開發成本很低,易于上手。

2.4.2 訪問手機中的文件夾

前一小節中是將文件存放到SD卡中,其實文件也可以存放在手機內部存儲(ROM,相當于PC的硬盤)中。不過在Android系統中,其為每個應用程序在手機的ROM中都分配了一個私有的目錄,命名規則為“/data/data/<應用程序的包名>”。例如,應用程序的包名為“com.bn”,則系統分配的私有目錄為“/data/data/com.bn”。

應用程序開發時,若需要在ROM中存放文件,一般應該存放到系統分配的私有目錄中。啟動Eclipse,進入其中的DDMS面板,打開File Explorer,即可查看手機ROM中的文件組織情況,如圖2-17所示。

▲圖2-17 查看手機內部存儲文件

下面給出一個瀏覽手機ROM中文件夾的小案例,通過單擊文件夾的名稱,可以打開相應的文件夾,顯示其中的文件列表。運行本案例,其運行效果如圖2-18、圖2-19和圖2-20所示。

▲圖2-18 程序初始運行

▲圖2-19 進入dev目錄

▲圖2-20 單擊出錯

提示

圖2-18為程序一開始運行,顯示“/”目錄下內容的情況。圖2-19為單擊進入了dev目錄,圖2-20為單擊了不允許進入或不是文件夾的條目。

了解了本案例的運行效果之后,接下來對本案例中唯一的類—Sample2_6_Activity進行開發,具體代碼如下。

代碼位置:見隨書中源代碼/第2章/Sample2_6/src/com/bn/pp6目錄下的Sample2_6_Activity.java。

      1     package com.bn.pp6;                                       //聲明包
      2     import java.io.File;                                      //引入相關類
      3     ……//此處省略了部分類的引入代碼,讀者可自行查看隨書的源代碼
      4     import android.widget.AdapterView.OnItemClickListener;    //引入相關類
      5     public class Sample2_6_Activity extends Activity {        //創建Activity
      6           String currPath;                           //當前路徑字符串
      7           String rootPath = "/";                    //根目錄路徑
      8           TextView currDirTV;                       //顯示當前路徑的TextView引用
      9               @Override
      10             public  void  onCreate(Bundle  savedInstanceState)  {
      11                     super.onCreate(savedInstanceState);
      12                setContentView(R.layout.main);    //跳轉到主界面
      13                final ListView lv=(ListView)this.findViewById(R.id.lv); //獲取ListView
      14                Button back = (Button) this.findViewById(R.id.back);   //獲取返回按鈕
      15                     final  File[]  files  =  getFiles(rootPath);
                                                          //調用getFiles方法獲取根目錄下文件列表
      16                currDirTV = (TextView) this.findViewById(R.id.currDirTV); //獲取ListView
      17                     currPath  =  rootPath;
      18                currDirTV.setText("當前路徑:" + currPath);      //設置當前路徑
      19                initListView(files, lv);                           //初始化顯示列表
      20                back.setOnClickListener                            //返回按鈕監聽器
      21                     (new  OnClickListener()  {
      22                              @Override
      23                              public  void  onClick(View  v)  {
      24                                      if  (! currPath.equals(rootPath))  {
                                                          //若當前路徑不是根目錄,返回到上一層目錄
      25                                  File f = new File(currPath); //獲取當前路徑下的文件列表
      26                                  f = f.getParentFile();      //獲取當前路徑的上層路徑
      27                                  currPath = f.getPath();    //更改當前路徑
      28                                  currDirTV.setText("當前路徑:" + currPath); //設置當前路徑
      29                                  initListView(getFiles(currPath), lv); //初始化顯示列表
      30             }}}); }
      31          //獲取當前目錄下的文件列表的方法
      32             public  File[]  getFiles(String  filePath)  {
      33                File[] files = new File(filePath).listFiles(); //獲取當前目錄下的文件列表
      34                return files;                             //返回文件列表
      35             }
      36          ……//此處省略了初始化ListView的方法,讀者可以自行查閱隨書中的源代碼
      37     }

? 第9-30行為案例整體功能的實現代碼。程序運行時,首先調用initListView方法初始化文件顯示列表,顯示根目錄下的文件情況。然后給“返回上一層”按鈕添加了監聽器,監聽器功能為若存在上一層目錄,則刷新文件顯示列表為上一層目錄下的情況。

? 第32-35行為獲取當前路徑下所有文件列表的方法。該方法中首先需要獲得當前路徑對應的File對象,之后返回其下對應的文件列表。

提示

由于篇幅所限,初始化文件列表的代碼省略,有需要的讀者請自行查閱中的源代碼進行學習。

2.4.3 讀取assets文件夾下的內容

Android還能將應用程序所需的數據文件打包到apk文件中,省去了使用者安裝應用程序后還需要下載數據包的情況。但是要注意的是,打包到apk文件中的數據文件并不是可以放在任何位置,一般應該放到項目中的assets文件夾下。

提示

對于特別大(如50MB)的數據文件,在實際開發中一般還是與apk安裝文件分開的。對于不大的數據文件,就非常適合打包到apk包中的assets文件夾下。

下面將通過一個小案例來說明如何編程訪問assets文件夾下的內容,其主要功能是完成對應用程序內部的assets文件夾下文件的讀取。操作過程為首先在案例初始界面輸入文件名,然后單擊打開按鈕。若存在該文件,則在下方顯示出文件內容;反之,則彈出Toast提示用戶重新輸入。案例運行效果如圖2-21和圖2-22所示。

▲圖2-21 程序運行效果圖

▲圖2-22 無法找到指定文件

了解了本案例的功能后,下面來介紹本案例的開發過程,具體步驟如下。

(1)首先將AndroidIO.txt文本文件復制到項目中的assets文件夾中,如圖2-23所示。

▲圖2-23 添加文本文件

(2)將AndroidIO.txt文本文件復制到項目中的assets文件夾后,接下來將開發本案例中唯一的類Sample2_7_Activity,其代碼如下。

代碼位置:見隨書中源代碼/第2章/Sample2_7/src/com/bn/pp7目錄下的Sample2_7_Activity.java。

      1       package  com.bn.pp7;
      2     import java.io.ByteArrayOutputStream;                        //引入相關包
      3     public class Sample2_7_Activity extends Activity {   //創建Activity
      4            @Override
      5         public void onCreate(Bundle savedInstanceState) { //重寫onCreate方法
      6                 super.onCreate(savedInstanceState);
      7             setContentView(R.layout.main);                   //跳轉至主界面
      8             Button ok=(Button)this.findViewById(R.id.Button01);     //獲取打開按鈕引用
      9             ok.setOnClickListener(                            //為打開按鈕添加監聽器
      10                  new  OnClickListener()  {
      11                     public  void  onClick(View  v)  {
      12                              EditText  et1=(EditText)findViewById(R.id.EditText01);
      13                      //調用loadText方法獲取對應文件名的文件
      14                              String  nr=loadText(et1.getText().toString().trim());
      15                              EditText  et2=(EditText)findViewById(R.id.EditText02);
      16                      et2.setText(nr);                         //設置顯示框內容
      17             }}); }
      18        public String loadText(String name){                //加載assets文件方法
      19          String nr=null;                                      //內容字符串
      20          try {                                                  //打開對應名稱文件的輸入流
      21                     InputStream  is=this.getResources().getAssets().open(name);
      22                     int  ch=0;
      23                //創建字節數組輸出流
      24                     ByteArrayOutputStream  baos=new  ByteArrayOutputStream();
      25                while((ch=is.read())! =-1){baos.write(ch); }//讀取文件
      26                byte[] buff=baos.toByteArray();             //轉化為字節數組
      27                baos.close();                                  //關閉輸入輸出流
      28                is.close();                                     //關閉輸入輸出流
      29                nr=new String(buff, "utf-8");                 //轉碼生成新字符串
      30                nr=nr.replaceAll("\\r\\n", "\n");            //替換換行符等空白字符
      31                } catch (Exception e) {                       //沒有找到對應文件,進行提示
      32                      Toast.makeText(getBaseContext(), "對不起,沒有找到指定文件。",
      33                              Toast.LENGTH_LONG).show();
      34                     }
      35                return nr;                                      //返回內容字符串
      36     }}

? 第8-17行首先獲取了打開按鈕的引用,然后給此按鈕添加了監聽器。監聽器的功能為讀取用戶輸入名稱的文件內容,并顯示到界面上。

? 第18-36行為從assets中加載指定名稱文本文件的方法,其首先獲取了指向指定文件的輸入流,然后從輸入流中讀取數據,接著將數據編碼為字符串,并替換換行符等空白字符,最后返回加載的內容。

提示

通過上述案例的介紹,相信讀者對Android平臺下文件的存儲和讀取已經有所掌握。在真正的開發過程中,開發人員應該考慮各方面的因素,在需要時采用最適合自己的存儲方式進行存儲。

主站蜘蛛池模板: 昔阳县| 凤冈县| 安吉县| 海兴县| 湖南省| 台山市| 观塘区| 抚松县| 尼木县| 如东县| 当雄县| 洞口县| 镇平县| 中方县| 吉林市| 锦屏县| 安阳县| 灌南县| 大厂| 调兵山市| 孟村| 班戈县| 阿坝| 桐乡市| 卢氏县| 历史| 六安市| 泽州县| 赤城县| 特克斯县| 怀安县| 嘉祥县| 石嘴山市| 霍州市| 华阴市| 高青县| 哈密市| 临沂市| 吉木萨尔县| 准格尔旗| 临猗县|