《OpenGL ES 3.x游戏开发(上卷)》一2.4 文件I/O
本节书摘来异步社区《OpenGL ES 3.x游戏开发(上卷)》一书中的第2章,第2.4节,作者: 吴亚峰 责编: 张涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。
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平台下文件的存储和读取已经有所掌握。在真正的开发过程中,开发人员应该考虑各方面的因素,在需要时采用最适合自己的存储方式进行存储。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
《深入解析Android 虚拟机》——第1章,第1.4节编译Android Kernel
本节书摘来自异步社区《深入解析Android 虚拟机》一书中的第1章,第1.4节编译Android Kernel,作者 钟世礼,更多章节内容可以访问云栖社区“异步社区”公众号查看 1.4 编译Android Kernel编译Android Kernel代码就是编译Android内核代码,在进行具体编译工作之前,需要先了解在Android开源系统中包含的以下3部分代码。 仿真器公共代码:对应的工程名是kernel/common.get。MSM平台的内核代码:对应的工程名是kernel/msm.get。OMAP平台的内核代码:对应的工程名是kernel/omap.get。在本节的内容中,将详细讲解编译上述Android Kernel的基本知识。 1.4.1 获取Goldfish内核代码Goldfish是一种虚拟的ARM处理器,通常在Android的仿真环境中使用。在Linux的内核中,Goldfish作为ARM体系结构的一种“机器”。在Android的发展过程中,Goldfish内核的版本也从Linux 2.6.25升级到了Linux 3.4,此处理器的Linux内核和标准的Linux内核...
- 下一篇
《移动App测试的22条军规》——第23章,第20节对微信App进行性能测试和安全性测试
本节书摘来自异步社区《移动App测试的22条军规》一书中的第23章,第20节对微信App进行性能测试和安全性测试,作者 黄勇,更多章节内容可以访问云栖社区“异步社区”公众号查看 23.20 对微信App进行性能测试和安全性测试(1)对微信App进行性能测试,我们可以选择在低网速的网络环境中(例如2G网络)测试微信App的登录(如图23.59所示)和刷新朋友圈(如图23.60所示)的功能。 (2)我们可以通过使用Android SDK中自带的DDMS工具来检查微信App发送的请求是否安全(如图23.61所示)。 微信App发送的请求在DDMS中都没有明文传输数据 我们还可以查看微信App存储文件的内容,以验证这些数据是否安全(如图23.62所示)。 微信App保存在设备上的数据文件(非图片和语音等用户手动存储的文件)都进行了加密
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8编译安装MySQL8.0.19
- Red5直播服务器,属于Java语言的直播服务器
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题