File Writer Java;如何覆盖

时间:2012-06-29 10:31:21

标签: java file writer

我正在为我的游戏制作一个Highscore实现。这就是我想要做的: 我有对象分数,其中包含字符串名称和整数分数。 现在:

  • 如果文件中尚未包含名称,请添加
  • 如果Name在文件中,在空格后取字符串并转换为整数,所以我得到了分数。

现在,如果得分比实际好,我必须在文件上覆盖它... 这是我的问题......我可以这样做吗?如何在文件的某个位置准确地将字符串写在另一个字符串上?

5 个答案:

答案 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>会更好地为你服务......