1

我正在为我的游戏制作高分实现。这就是我想做的事情:我有包含字符串名称和整数分数的对象分数。现在 :

  • 如果 Name 不在文件中,则添加它
  • 如果名称在文件上,则在空格后取字符串并转换为整数,所以我得到了分数。

现在,如果分数比实际分数好,我必须在文件上覆盖它……这是我的问题……我可以这样做吗?我怎样才能在文件的某个点将一个字符串准确地写入另一个字符串?

4

5 回答 5

4

对于这种需求,通常认为替换文本文件中的文本过于繁琐,因此通常的做法是读入整个文件,进行替换并编写整个文件的新版本。如果您有大量数据,您将使用数据库或 NoSQL 解决方案。

PS考虑使用序列化,它可以使事情变得更容易。

于 2012-06-29T10:34:44.260 回答
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

不能将 joe 的分数替换为 10,除非您填充了一堆空格。

如果这是您的数据文件,那么您绝对必须重写整个文件(即使您编写额外的代码仅从更改点开始重写 - 从统计上讲,这将是文件的 50%,因此不值得烦人。

另一件事——如果你重写,你有缩短文件的风险。为此你需要调用 raf.setLength(0); 在写入第一个字节之前。否则,您会在新文件末尾看到幻影文本。

于 2012-06-29T10:46:41.823 回答
1

我有包含字符串名称和整数分数的对象分数。

Properties为此请使用文件。它提供了一个简单的界面来加载和保存文件、获取键(名称)以及设置或检索值(分数)。 String值被存储,但它们可以轻松地转换为整数。

于 2012-06-29T10:39:49.720 回答
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 成本。

于 2015-03-30T00:27:07.843 回答
-1

只是一个想法,名称和分数的文件存储有什么具体原因吗?

似乎aMap<String, Integer>会更好地为您服务...

于 2012-06-29T10:34:31.543 回答