我正在为我的游戏制作高分实现。这里有我想要做的: 我有对象分数,其中包含字符串名称和整数分数。 现在:文件编写器Java;如何覆盖
- 如果名称是不是已经在该文件中,添加它
- 如果名称是文件,一个空间后取字符串并将其转换为整数,所以我得到的分数。
现在,如果分数比实际更好,我必须在文件上覆盖它... 这是我的问题..我可以这样做吗?我怎样才能在文件的某个点上准确地写入另一个字符串?
我正在为我的游戏制作高分实现。这里有我想要做的: 我有对象分数,其中包含字符串名称和整数分数。 现在:文件编写器Java;如何覆盖
现在,如果分数比实际更好,我必须在文件上覆盖它... 这是我的问题..我可以这样做吗?我怎样才能在文件的某个点上准确地写入另一个字符串?
只是一个想法,文件存储名称和分数的任何具体原因?
似乎是一个Map<String, Integer>
将有助于你更好......
显然,高分需要持久。 –
对我而言没有用 –
通常它被认为过于繁琐,以取代在文本文件中的文本对于这种要求,因此通常的方式做到这一点仅仅是阅读整个文件,进行替换并写入整个文件的新版本。如果您有大量数据,则可以使用数据库或NoSQL解决方案。
P.S.考虑使用序列化,它可以让事情变得更容易。
我有包含字符串名称和整数分数的对象得分。
改为使用Properties
文件。它提供了一个简单的界面来加载保存文件,获取键(名称)和设置或检索值(分数)。 String
值存储,但它们可以轻松地转换为/从整数。
我同意这最好通过完全重新序列化整个数据库来完成。在现代计算机上,每个磁盘可以推送30MB/s用于线性写入(如果有足够的缓存,则可以更多)。如果你处理的数据超过30MB,你真的需要一个数据库(HSQLDB,DerbyDB,BerkleyDB)是简单的数据库。或者一路去postgres/mysql。
但是,要覆盖现有文件的固定大小部分的方式(或者更确切地说,效仿这样的方式),是使用:
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
try {
raf.seek(position);
raf.writeInt(newScore);
raf.close();
} finally { raf.close(); }
注意使用writeInt代替raf.write的(Integer.toHexString(newScore).getBytes()),因为你确实需要在大小上进行修正。
现在,如果文本文件是内在的ascii(例如人类将读取文件),因此该值不能是二进制的。也许你可以保留它的HexString(因为这将是固定的大小),或你可以填零十进制字符串:
但绝对肯定不能做的是将字符串增长1个字节。 所以:
bob 15
joe 7
nina 981
不能有乔的分数换成10,除非你已经填补了一堆的空间。
如果这是您的数据文件,那么您绝对必须重写整个文件(即使您编写额外的代码以仅从更改点重写 - 统计上该文件将占文件的50%因而不值得打扰其他
一两件事 - 如果你不重写,你缩短了文件的风险。对于您需要调用 raf.setLength(0); 写的第一个字节之前。否则,你会在新文件末尾看到幻影文字
final Map<String,Long> symbol2Position = new ConcurrentHashMap<>();
final Map<String,Integer> symbol2Score = new ConcurrentHashMap<>();
final String fileName;
final RandomAccessFile raf;
// ... skipped code
void storeFull() {
raf.position(0);
raf.setLength(0);
for (Map.Entry<String,Long> e : symbol2Position.entrySet()) {
raf.writeUTF8(e.getKey());
raf.write(',');
symbol2Score.put(e.getKey(), raf.position());
raf.writeUTF8(String.format("%06d",e.getValue()));
raf.write('\n');
}
}
void updateScore(String key, int newScore) {
if (symbol2Score.containsKey(key)) {
symbol2Score.put(key, newScore);
raf.position(symbol2Position.get(key));
raf.writeString(String.format("%06d", newScore));
} else {
symbol2Score.put(key, newScore);
long fileLen = raf.length();
symbol2Position.put(key, fileLen);
raf.position(fileLen);
raf.writeString(String.format("%06d", newScore));
}
}
我可能会ra使用DB或二进制映射文件..每个字段含有8B,4B指向用户名位置,4B代表分数。但是,这允许用户可读的数据文件,同时更新速度比重写属性文件更快。
查看LevelDB - 这个星球上嵌入式系统最快的DB。 :)它的主要作用就是每秒更新数千次/百万次,而不需要在多GB文件中随机更新6个字节的rand-seek-rewrite成本。
你真的需要在同一个地方覆盖文本,还是只需要记录新的高分?例如使用属性可能是最简单的,但这不会保留条目的顺序。 –