注意事项:
(关于此答案的注意事项:此处的文件引用内部/外部存储,而不是 SharedPrefs)
SQL:
- 数据库有开销,会占用大小
- 如果数据库或表损坏,所有数据都会丢失(这有多糟糕取决于您的应用。丢失数千张图片:糟糕。丢失删除日志:不是很糟糕)
- 可以压缩数据库(见this)
- 如果您遇到 ID 问题(或识别行 X 的任何方式),您可以将数据拆分到不同的表中,这意味着一个数据库可以为每个对象有多个表,其中对象 X 与对象 Y 的识别冲突。基本上意味着您可以将所有内容保存在一个文件中,并且仍然避免与名称冲突。 (阅读答案底部的更多信息)
文件:
- 每个文件都必须定义为自己的独立文件,占用空间(文件名)
- 您不能将所有属性存储在一个文件中,而无需设置一个高级阅读器来确定不同类型的数据。如果您不这样做,并且每个属性都有一个文件,那么您将使用大量空间。
- 读取数千行可能会很慢,尤其是当您有多个(例如 100 多个)非常大的文件时
操作系统为每个文件使用空间,不包括内容。占用空间的实例的文件名。但要记住的是,您可以将应用程序的所有数据保存在一个文件中。如果您有一个应用程序,其中两种不同类型的对象可能存在命名问题,您可以创建一个新数据库。
命名冲突
假设你有两个对象,对象 X 和 Y。
场景 1'
对象 X 存储两个变量。文件名是(x 和 y 在这种情况下是坐标):
x.txt
y.txt
但在以后的版本中,对象 Y 带有相同的两个文件。
所以你必须为对象 X 和 Y 分配一个 ID:
0-x.txt
0-y.txt
每个文件仅在名称上使用 3 个字符(总共 7 个字符,包括扩展名)。设置越复杂,它就越大。见场景 2
但是保存在数据库中,您会得到 ID 为 0 的行并找到 X 或 Y 列。
您不必担心文件名。
此外,如果每个对象都保存了很多文件,那么加载或保存每个文件的引用将占用大量空间。这会影响您的 APK 文件,并慢慢将您推向 50 MB 限制(谷歌播放限制)。
您可以创建通用方法,但您可以使用 SQL 执行相同的操作并节省 APK 文件中的空间。但与文本文件相比,SQL 在名称方面确实节省了一些空间。
但请注意,如果您保存 2-3 个文件(只是为了取一个数字),那么名称中的那几个字节无关紧要
当您开始保存数百个文件、长名称以避免命名冲突时,这就是 SQL 为您节省空间的时候。如果表格太大,您可以压缩它。您可以压缩文本文件以节省一些空间,但对于单行文件,没有太多可节省的空间。
场景 2
对象 X 和 Y 各有三个孩子。
每个孩子都有 3 个变量保存到文件系统中。如果只有一个对象有 3 个孩子,它可以像这样保存它
[id][variable name].txt
但是因为有另一个父级有 3 个子级(相同类型,并且他们保存相同的文件),所以最后保存的对象的子级是保持保存状态的子级。前 3 个被覆盖。
所以你必须添加父 ID:
[parent ID][child ID][variable name].txt
请记住,这些示例集中在几个对象上。节省的空间量很少,但是当您保存数百个(如果不是数千个)文件时,就是您开始节省空间的时候了。
现在,如果您创建一个表,您可以存储您的主要对象(在本例中为 X 和 Y)。然后,您可以创建第一个表以使其可识别对象是父对象还是子对象,也可以创建第二个表。第二个表有两个 ID 值;一个用来识别父母,一个用来识别孩子。因此,如果您想查找对象 436 的所有子对象,只需编写以下查询:
SELECT * FROM childrentable WHERE `parent_id`='436'
这将为您提供以对象 436 作为其父对象的所有子对象的所有属性。
返回时所有内容都存储在光标中。
如果你要对文件做同样的事情,这一行(Saver 是文件保存和加载类):
Saver.load("0-436-file_name", context);
当然,可以使用 for 循环来循环子 ID(开头为 0),但您还必须保存有多少子 ID:您无法轻松获取文件,所以你必须存储关于对象数量和对象子对象的值。
这意味着您必须在更多文件中保存更多值才能获取您最初保存的文件。这是一种非常困难的做事方式。数据库将帮助您不必编写文件来跟踪您保存了多少文件。数据库将在每个查询上返回 [x] 结果。因此,如果对象 436 没有子对象,则 SQL 返回 0 行。但是在文件中,您必须将 0 保存为孩子的数量。猜测文件名会导致 I/O 异常。