我正在为我的游戏制作一个Highscore实现。这就是我想要做的: 我有对象分数,其中包含字符串名称和整数分数。 现在:
现在,如果得分比实际好,我必须在文件上覆盖它... 这是我的问题......我可以这样做吗?如何在文件的某个位置准确地将字符串写在另一个字符串上?
答案 0 :(得分:4)
一般来说,为了满足这种要求而无法替换文本文件中的文本,因此通常的方法就是读取整个文件,进行替换并编写整个文件的新版本。如果您有大量数据,则可以使用数据库或NoSQL解决方案。
P.S。考虑使用序列化,它可以使事情变得更容易。
答案 1 :(得分:1)
我的对象分数包含字符串名称和整数分数。
请使用Properties
文件。它提供了一个简单的加载接口和保存文件,获取密钥(名称)并设置或检索值(分数)。存储String
个值,但可以轻松地将它们转换为整数/从整数转换。
答案 2 :(得分:1)
我同意这最好通过完全重新序列化整个数据库来完成。在现代计算机上,每个磁盘可以推送30MB / s进行线性写入(如果有足够的缓存,则更多)。如果你处理超过30MB的数据,你真的需要一个数据库(HSQLDB,DerbyDB,BerkleyDB)是微不足道的数据库。或者一直到postgres / mysql。
但是,覆盖现有文件的FIXED大小部分(或者更确切地说,模仿这样做的方式)的方法是使用:
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); 在写第一个字节之前..否则,您将看到超出新文件末尾的幻像文本。
答案 3 :(得分: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));
}
}
我可能更喜欢使用DB或二进制映射文件..意思是每个字段有8B的文件,4B指向用户名位置,4B代表分数。但这允许使用人类可读的数据文件,同时更新速度比仅重写属性文件更快。
查看LevelDB - 这个星球上最快的数据库,用于嵌入式系统。 :)它在上面的主要内容是每秒数千/数百万次更新,而不需要在多GB文件中随机更新6个字节的rand-seek-rewrite成本。
答案 4 :(得分:-1)
只是一个想法,文件存储名称和分数的任何具体原因?
好像Map<String, Integer>
会更好地为你服务......