【问题标题】:Java UTF-8 Encoding with FileWriter使用 FileWriter 进行 Java UTF-8 编码
【发布时间】:2015-03-23 04:37:15
【问题描述】:

我目前正在用 java 制作一个带有随机世界生成的游戏,在游戏开始时我希望它存储图块 ID、X 位置和 Y 位置,以便当我重新加载游戏时它会能够再次生成它。

当我编写文件时,一切正常,但我有一个问题,文件的输出是一种奇怪的字符组合。

代码:

import java.io.*;

public class FileWrite {    
    public static FileWriter writeFile;
    public static BufferedWriter write;

    public static void recordItem(int blockID, int blockX, int blockY, String filePath, String fileName) throws Exception {
        writeFile = new FileWriter("res/save/" + filePath+ fileName, true);
        write = new BufferedWriter(writeFile);

        write.write(blockID);
        write.write(blockX);
        write.write(blockY);
        write.newLine();
        write.flush();
    }
}

文件输出:

 @ 
 ` 
 ? 
   
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 

如何将我的 FileWriter 编码为 UTF-8 以显示数字?谢谢您的帮助。 :)

【问题讨论】:

    标签: java encoding utf-8 java-io filewriter


    【解决方案1】:

    只是一个建议,如果您想使持久化信息的形式更加健壮,您可以考虑对象序列化。这比听起来容易。只需有一个实现 Serializable 的静态内部类,如下所示:

    static class JunkRec implements Serializable
    {
        private static final long serialVersionUID = 1L;
        final int _blockID, _blockX, _blockY;
        final String _filePath, _fileName;
        public JunkRec(int blockID, int blockX, int blockY, 
                        String filePath, String fileName) 
       {
            _blockID = blockID;
            _blockX = blockX;
            _blockY = blockY;
            _filePath = filePath;
            _fileName = fileName;
        }
        @Override
        public String toString() {
            return String.format("id=%08d x=%04d y=%04d fp=%s fn=%s", 
                    _blockID, _blockX, _blockY, _filePath, _fileName);
        }
    }
    

    现在,一种存储 JunkRec 的方法...

    public static void storeJunk(JunkRec jr)
    {
        try (
            FileOutputStream fos = new FileOutputStream(
                    jr._filePath + jr._fileName + ".ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);) {
            oos.writeObject(jr);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    

    给定文件名的另一种恢复 JunkRec 的方法。

    public static JunkRec retrieveJunk(String filePath, String fileName)
    {
        try (
            FileInputStream fis = new FileInputStream(
                    filePath + fileName + ".ser");
            ObjectInputStream ois = new ObjectInputStream(fis);) {
            return (JunkRec) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    最后是 main() 中的一个小测试驱动程序...

    public static void main(String[] args)
    {
        // generate and restore 10 records
        Random r = new Random();
        List<String> names = new ArrayList<>();
        /* do a few in two ways */
        for (int i = 0; i < 5; ++i) {
            int blk = r.nextInt(10000);
            String fname = String.format("BLKID_%02d", i);
            if (names.add(fname)) {
                JunkRec jr = new JunkRec(
                        r.nextInt(10000),
                        r.nextInt(50),
                        r.nextInt(50),
                        "/tmp/",
                        fname);
                storeJunk(jr);
                System.out.println("Wrote: "+jr);
            }
        }
    
        /* read them all back */
        for (String fname : names) {
            JunkRec jr = retrieveJunk("/tmp/", fname);
            System.out.println("Retrieved: " + jr + " from " + fname);
        }
    
        /* clean up */
        for (String fname : names) {
            ((File) new File("/tmp/" + fname + ".ser")).delete();
        }
    }
    

    这不是生产质量的代码,但它显示了序列化是多么容易。有一个陷阱,但总的来说,序列化是基于文件的持久性的可靠解决方案。

    只是一个建议。 玩得开心!

    【讨论】:

    • 感谢您的建议。 :)
    【解决方案2】:

    write 方法写入单个字符,因此您正在使用 Unicode 代码点 blockID、blockX、blockY 写入字符,这不是您想要的。

    您的 Writer 是否编码为 UTF-8 在这里并不那么重要,尽管如果您希望文件可跨机器移植,明确编码总是好的,因此请尝试 new OutputStreamWriter(new FileOutputStream("res/save/" + filePath+ fileName, true), "UTF-8"); 而不是直接创建 FileWriter .直接创建它不允许你指定编码。

    改为执行以下操作:

    writer.write(String.format("%d %d %d\n", blockID, blockX, blockY));
    

    这会将您的三个数字格式化为一行中的一个字符串,然后将其发送到文件。

    请注意,您不应该在每次要写入一行时都创建一个新的 Writer/BufferedWriter。您应该将它们保存在类字段中并重复使用相同的编写器。您还需要在完成文件后关闭该文件,因为操作系统对您同时打开的文件数量有限制,而您当前的代码将很快用完该数量。

    【讨论】:

    • 非常感谢!我按照你的建议做了,它奏效了!我也会努力做你所说的其他事情,非常感谢。 :)
    猜你喜欢
    • 2015-10-26
    • 2016-05-10
    • 1970-01-01
    • 2018-10-25
    • 2012-04-08
    • 2017-01-24
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多