《OpenGL ES 3.x游戏开发(上卷)》一2.4 文件I/O

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所示。

提示

运行本案例时要注意SD卡中文本文件的编码格式,在Android系统中一般要采用UTF-8编码才能保证没有乱码出现。编码格式为UTF-8的文本文件,见随书中源代码/第2章目录下的AndroidIO.txt,读者可以将该文件导入到手机或模拟器的SD卡中再对本案例进行测试。

2.案例的开发
介绍完本案例的运行效果以及文本文件编码的注意事项后,接下来将对本案例的主控制类Sample2_5_Activity进行开发,其代码如下。

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所示。

下面给出一个浏览手机ROM中文件夹的小案例,通过单击文件夹的名称,可以打开相应的文件夹,显示其中的文件列表。运行本案例,其运行效果如图2-18、图2-19和图2-20所示。


提示

图2-18为程序一开始运行,显示“/”目录下内容的情况。图2-19为单击进入了dev目录,图2-20为单击了不允许进入或不是文件夹的条目。

了解了本案例的运行效果之后,接下来对本案例中唯一的类——Sample2_6_Activity进行开发,具体代码如下。

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所示。

了解了本案例的功能后,下面来介绍本案例的开发过程,具体步骤如下。

(1)首先将AndroidIO.txt文本文件复制到项目中的assets文件夹中,如图2-23所示。


(2)将AndroidIO.txt文本文件复制到项目中的assets文件夹后,接下来将开发本案例中唯一的类Sample2_7_Activity,其代码如下。

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平台下文件的存储和读取已经有所掌握。在真正的开发过程中,开发人员应该考虑各方面的因素,在需要时采用最适合自己的存储方式进行存储。

时间: 2024-11-02 12:09:51

《OpenGL ES 3.x游戏开发(上卷)》一2.4 文件I/O的相关文章

《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》——6.4节点法向量和面法向量

6.4 点法向量和面法向量 OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例 本章前面几节的案例都是基于球面开发的,球面属于连续.平滑的曲面,因此面上的每个顶点都有确定的法向量.但现实世界中的物体表面并不都是连续.平滑的,此时对于面上的某些点的法向量计算就不那么直观了,图6-18说明了这个问题. 从图6-18中可以看出,顶点A位于长方体左.上.前3个面的交界处,此处是不光滑的.这种情况下顶点A的法向量有两种处理策略,具体如下所列. 在顶点A的位置放置3个不同的顶点,每个顶点看作是仅

《OpenGL ES 3.x游戏开发(上卷)》一第1章 Android概述

第1章 Android概述 OpenGL ES 3.x游戏开发(上卷)随着移动互联网时代的到来,智能手机逐渐走进了人们的生活, Google公司于2007年11月5日发布了基于Linux平台的开源手机操作系统--Android.由于Android系统的开源性以及其他各个方面的因素,其受到了广大手机厂商的青睐,因此需要大量的Android开发人员来满足日益增长的海量软件开发需求. 提示 有些读者可能会有一点奇怪,不是介绍OpenGL ES 3.0的知识吗,怎么一开始就介绍Android呢?这是因为

《OpenGL ES 3.x游戏开发(上卷)》一第2章 游戏开发相关的 Android基础知识

第2章 游戏开发相关的 Android基础知识 OpenGL ES 3.x游戏开发(上卷)虽然本书主要是介绍OpenGL ES 3.0 3D应用及游戏开发的,但由于很多3D游戏应用中还需要用到目标平台的一些其他应用开发方面的知识,而本书3D基础知识部分主要是借助于Android平台来介绍OpenGL ES 3.0 3D应用及游戏开发的.故本章将向读者简要介绍一些在Android游戏开发中必备的一些基础知识,如音效.文件的读取.游戏信息的存储.Socket网络.蓝牙网络等. 提示 由于介绍Andr

OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一6.3 定位光与定向光

6.3 定位光与定向光 OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例上一节中介绍的光照效果都是基于定位光光源的,定位光光源类似于现实生活中的白炽灯灯泡,其在某个固定的位置,发出的光向四周发散.定位光照射的一个明显特点就是,在给定光源位置的情况下,对不同位置的物体产生的光照效果不同. 现实世界中并不都是定位光,例如照射到地面上的阳光,光线之间是平行的,这种光称为定向光.定向光照射的明显特点是,在给定光线方向的情况下,场景中不同位置的物体反映出的光照效果完全一致.图6-16中对定位

《OpenGL ES 3.x游戏开发(下卷)》一导读

前 言 OpenGL ES 3.x游戏开发(下卷) 为什么要写这样一套书 随着智能手机硬件性能的不断提升,如"水果忍者""极品飞车""狂野飙车8:极速凌云"等一批优秀的3D游戏娱乐应用在广大智能机用户间流行开来.与此同时,也带动了手机游戏产业逐渐从2D走向3D.但目前国内专门介绍3D游戏开发的书籍与资料都非常少,同时3D应用开发的门槛又比较高,使得很多初学者无从下手.根据这种情况,笔者结合多年从事3D游戏应用开发的经验编写了这样一套书. 了解一些

《OpenGL ES 3.x游戏开发(上卷)》一1.4 已有Android项目的导入和运行

1.4 已有Android项目的导入和运行 上一节介绍了如何搭建Android开发环境.如何开发Hello Android应用程序以及如何调试Android的应用程序,接下来在本节中将简要介绍已有Android项目的导入和运行. 1.4.1 项目的导入 首先介绍怎样将已有的Android项目导入Eclipse,此处以本书最后部分大案例中的"3D可爱抓娃娃"为例进行讲解,具体步骤如下. (1)启动Eclipse,依次单击"File|Import",系统将弹出导入项目的

《OpenGL ES 3.x游戏开发(上卷)》一2.7 小结

2.7 小结 本章主要对Android平台下游戏开发中可能会用到的Android平台的相关基础知识进行详细介绍,如文件的I/O操作.SQLite数据库的增.删.改.查,游戏中声音特效.蓝牙互连等.只有学好这些基础知识,开发人员才能开发出更好的Android手机游戏.读者一定要在这些基础上下足工夫,今后的开发道路才会一帆风顺. 提示 Android平台的其他相关知识还有很多,由于本书侧重于介绍OpenGL ES 3.0 3D应用程序的开发,故本章只是简单介绍了一些与3D开发不直接相关的,但在游戏开

《OpenGL ES 3.x游戏开发(上卷)》一导读

前 言 为什么要写这样一本书随着智能手机硬件性能的不断提升,如水果忍者.极品飞车.狂野飙车等一批优秀的3D游戏娱乐应用在众多智能机用户间流行开来.与此同时,也带动了手机游戏产业逐渐从2D走向3D.但目前国内专门介绍这方面开发的书籍与资料都非常少,同时3D应用开发的门槛又比较高,使得很多初学者无从下手.根据这种情况,笔者结合多年从事3D游戏应用开发的经验编写了本书. 了解一些3D开发领域的技术人员都知道,移动嵌入式平台上的3D应用开发主要是基于OpenGL ES的3个版本,1.x.2.x和3.x.

《OpenGL ES 3.x游戏开发(上卷)》一1.5 Android应用程序运行的机制

1.5 Android应用程序运行的机制 前面介绍了如何搭建Android开发环境.如何开发Hello Android应用程序以及Android应用程序的调试,接下来在本节中将简要地介绍Android应用程序的运行机制. 1.5.1 应用程序的系统架构 Android平台由应用程序.应用程序框架.Android运行时.系统库以及底层Linux内核构成,详细结构如图1-68所示. 说明 应用程序层里面包含的就是需要读者去发挥创意开发的.各种各样丰富多彩的应用程序,这也是一般Android应用开发人

《OpenGL ES 3.x游戏开发(上卷)》一2.1 游戏中的音效

2.1 游戏中的音效 一款好游戏,除了具备优质的画面和较高的可玩性之外,还应该有出色的音效.音效一般指的是游戏中发生特定行为或进行特定操作时播放的效果音乐或为了渲染整体气氛播放的背景音乐等,如远处隆隆的炮声.由远而近的脚步声等. 开发人员通过精心准备的声音特效,并结合游戏酷炫的场景,可以渲染出一种紧张刺激的氛围,使玩家产生身临其境的感觉.这就像电影中的声音特效一样,假如没有了合适的音效,那么游戏和电影一样,真实感会大打折扣. 提示 按照作用的不同,可以将音效划分为即时音效和背景音乐.两种音效在A