LibGDX文件处理

本文为File handling的译文

介绍:
Libgdx应用程序在四个不同的平台上运行:桌面系统(Windows,Linux,Mac OS X,headless),Android,iOS和支持JavaScript / WebGL的浏览器。 这些平台中的每一个处理文件I/O方法有点不一样。

Libgdx's Files (code) 模块提供了以下的功能:

  1. 从文件读取
  2. 写入文件
  3. 复制一个文件
  4. 移动文件
  5. 删除文件
  6. 列出文件和目录
  7. 检查文件/目录是否存在

在我们可以深入了解Libgdx的这一方面之前,我们首先要查看所有支持平台的文件系统的不同概念。

文件系统

在这里我们简单复习下LibGDX所支持的文件平台系统

Desktop (Windows, Linux, Mac OS X, Headless)
在桌面操作系统上,文件系统是一块大内存。 文件可以使用 相对于当前工作目录(应用程序执行的目录)或绝对路径的路径 进行引用。 忽略文件权限,文件和目录通常可以被所有应用程序读写。

Android
在Android上,情况有点复杂。文件可以存储在应用程序的APK中作为资源或assets。 这些文件是只读的。 Libgdx只使用assets的机制,因为它提供了对字节流的原始访问,更类似于传统的文件系统。 Resources 更好地适用于正常的Android应用程序,但在游戏中使用时会引入一些问题。 Android会在加载时操纵它们,例如 它会自动调整图像大小。

Assets 存储在您的Android项目的Assets 目录中,并在部署应用程序时自动与您的APK一起打包。 Android系统上其他应用程序没有权限访问这些文件。

文件也可以存储在内部存储器中,它们是可读写的。 每个安装的应用程序都有专用的内部存储目录 该目录只能由该应用程序访问。 人们可以把这个存储看做是应用程序的私人工作区。

最后,文件可以存储在外部存储器上,如SD卡。外部存储可能不总是可用,例如 用户可以拔出SD卡。 因此,此存储位置中的文件应视为易失性。 您需要向您的AndroidManifest.xml文件添加权限才能允许写入外部存储,请参阅权限

IOS
在iOS上,所有文件类型都可用。

Javascript/WebGL
原始的JavaScript / WebGL应用程序没有传统的文件系统概念。 相反,资源(如图像)由指向一个或多个服务器上的文件的URL引用。 现代浏览器还支持本地存储,它靠近传统的读/写文件系统。 本地存储的问题是,默认情况下可用的存储量相当小,不是标准化的,并且没有(良好)的方式准确地查询配额。 因此,首选项API目前是在JS平台上持久编写本地数据的唯一方法。
Libgdx在巧妙地为您提供只读文件系统抽象。

文件(存储)类型

libgdx中的一个文件由FileHandle类的一个实例表示。 FileHandle有一个类型,它定义文件所在的位置。 下表说明了每个平台每种文件类型的可用性和位置。

Type Description, file path and features Desktop Android HTML5 iOS
Classpath Classpath文件直接存储在源文件中,它们被打进Jar里,并且始终是只读文件,They have their purpose, but should be avoided if possible. Yes Yes No Yes
Internal Android的Assets目录,桌面应用的根目录(或者说工作目录), GWT项目的 core/assets/目录,这些文件也是只读的,如果文件无法在内部存储器中找到,那么文件模块将转而向classpath文件中查找,这是非常有必要的,当用户使用Eclipse的Assets资源链接机制,请参阅Project Setup Yes Yes Yes Yes
Local Android应用程序内部私有存储路径,而对于桌面应用来说,Local和Internal是相同的。 Yes Yes No Yes
External Android上的SD卡根目录,桌面系统上当前用户的主目录 Yes Yes No Yes
Absolute 绝对文件需要指定其全限定路径。注意:为了可移植性,只有在绝对必要时才能使用此选项 Yes Yes No Yes

绝对路径文件和ClassPath文件主要用于桌面编辑器等对文件有复杂的I/O读写要求的情形,以至于对于游戏来说可以忽略它的安全要求,您应该使用的类型顺序如下:

Internal Files:与应用程序一起打包的所有资源(图像、音频等文件)都属于Internal Files,如果你使用Setup UI创建项目,只需将其放在Android项目的资源文件夹中即可。

Local Files:如果你需要读写少量的数据,比如保存游戏状态,那么使用本地文件吧,这些文件通常来说是你的应用程序私有的。 如果你想要一个键/值存储,你也可以使用Preferences

External Files: 如果你需要写入大量的数据,例如屏幕截图或从网络下载文件,你可以使用外部存储。 请注意,外部存储是易失的,用户可以删除它或删除您写的文件。 当用户卸载应用程序时,这些文件将不被删除。 因为它们没有被清理,所以使用本地文件存储通常更简单。

检查存储可用性和路径

根据应用程序运行的平台,不同的存储类型可能不可用。 您可以通过文件模块查询这种信息:

boolean isExtAvailable = Gdx.files.isExternalStorageAvailable();
boolean isLocAvailable = Gdx.files.isLocalStorageAvailable();

您还可以查询外部和本地存储的根路径:

String extRoot = Gdx.files.getExternalStoragePath();
String locRoot = Gdx.files.getLocalStoragePath();

获取FileHandles 句柄
FileHandle是通过直接从Files模块中使用上述类型之一获得的。 以下代码获取Internal Files 的myfile.txt文件的句柄。

FileHandle handle = Gdx.files.internal("data/myfile.txt");

如果你使用Setup UI创建项目的话,那么该文件包含在你的Android项目的Assets/data文件夹下,您的桌面项目和html项目将被Eclipse链接到此文件夹,并在Eclipse执行时自动选择该文件。

FileHandle handle = Gdx.files.classpath("myfile.txt");

“myfile.txt”文件位于ClassPath所在的目录或包含在jar文件中。

FileHandle handle = Gdx.files.external("myfile.txt");

在这种情况下,“myfile.txt”需要位于用户的主目录(Linux上的/home/<user>/myfile.txt,OSX上的/Users/<user>/myfile.txt和C:\ Users \ Windows上的<user> \ myfile.txt),以及Android上SD卡的根目录。

FileHandle handle = Gdx.files.absolute("/some_dir/subdir/myfile.txt");

在绝对路径文件句柄模式下,文件必须正好在完整路径的所在位置。如当前示例,myfile.txt文件应在windows/linux/ios/Android 当前驱动的/some_dir/subdir目录下.

列出并检查文件的属性

有时需要检查一个特定文件的存在或列出目录的内容。 FileHandle提供了简单的方法来做到这一点。
以下是一个示例,用于检查特定文件是否存在,以及文件实际上是否为目录。

boolean exists = Gdx.files.external("doitexist.txt").exists();
boolean isDirectory = Gdx.files.external("test/").isDirectory();

列出目录同样简单:

FileHandle[] files = Gdx.files.local("mylocaldir/").list();
for(FileHandle file: files) {
   // do something interesting here
}

注意:如果你不指定一个目录,则列表将为空。

桌面应用不支持列出internal Files的目录

我们还可以为 一个文件的父目录,或者为目录中的一个文件创建一个句柄

FileHandle parent = Gdx.files.internal("data/graphics/myimage.png").parent();
FileHandle child = Gdx.files.internal("data/sounds/").child("myaudiofile.mp3");

parent 句柄指向的是 "data/graphics/"
child 句柄指向的是 “data/sounds/myaudiofile.mp3"

FileHandle中有更多的方法让您检查文件的特定属性。 请参考Javadocs的详细信息。

注意:这些功能目前在HTML5后端大都没有实现。 如果HTML5将成为您的应用程序的主要平台,请尽量不要依赖它们。

错误处理

FileHandles上的某些操作可能会失败。 我们采用RuntimeExceptions来表示错误,而不是检查异常。 我们的推理是这样的:90%的时间我们将访问我们知道的文件,并且是可读的(例如与我们的应用程序一起打包的internal files)。

从文件读取

获取FileHandle之后,我们可以将其传递给一个知道如何从文件(例如图像)加载内容的类,或者让FileHandle自己处理它。 后者通过FileHandle类中的任何输入方法完成。 以下示例说明如何从内部文件加载文本:

FileHandle file = Gdx.files.internal("myfile.txt");
String text = file.readString();

如果您有二进制数据,您可以轻松地将文件加载到字节数组中:

FileHandle file = Gdx.files.internal("myblob.bin");
byte[] bytes = file.readBytes();

FileHandle类有更多的读取方法。 查看Javadocs了解更多信息。

写入文件

与读取文件类似,FileHandle还提供写入文件的方法。 请注意,只有local, external and absolute 类型支持写入文件。 将文字写入文件的工作原理如下:

FileHandle file = Gdx.files.local("myfile.txt");
file.writeString("My god, it's full of stars", false);

FileHandle#writeString的第二个参数指定内容是否应该附加到该文件。 如果设置为false,则文件的当前内容将被覆盖。

当然也可以将二进制数据写入文件:

FileHandle file = Gdx.files.local("myblob.bin");
file.writeBytes(new byte[] { 20, 3, -2, 10 }, false);

FileHandle中有更多的方法可以通过不同的方式进行编写,例如 使用OutputStream。 再次强调:参考Javadocs了解更多信息.

删除,复制,重命名和移动文件/目录

这些操作只能用于可写文件类型(local, external, absolute)。 但是请注意,复制操作的源也可以是只读FileHandle。 几个例子:

FileHandle from = Gdx.files.internal("myresource.txt");
from.copyTo(Gdx.files.external("myexternalcopy.txt"));

Gdx.files.external("myexternalcopy.txt").rename("mycopy.txt");
Gdx.files.external("mycopy.txt").moveTo(Gdx.files.local("mylocalcopy.txt"));

Gdx.files.local("mylocalcopy.txt").delete();

请注意,源和目标都可以是文件或目录。
有关可用方法的更多信息,请查看FileHandle Javadocs.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容