简体   繁体   English

使用FileWriter进行Java UTF-8编码

[英]Java UTF-8 Encoding with FileWriter

I am currently making a game in java with random world gen, at the beginning of the game I want it to store the tile ID, the X position, and the Y position so that when I re-load the game it will be able to generate it again. 我目前正在用随机世界生成的Java语言制作游戏,在游戏开始时,我希望它存储图块ID,X位置和Y位置,以便在我重新加载游戏时能够再次生成它。

When I write my file it all works but I have one issue, the output to the file is a weird combination of characters. 当我写文件时,所有文件都可以用,但是有一个问题,文件的输出是字符的怪异组合。

Code: 码:

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();
    }
}

Output in file: 文件输出:

 @ 
 ` 
 ? 
   
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 
 ? 

How do I encode my FileWriter to UTF-8 so it displays numbers? 如何将FileWriter编码为UTF-8,以便显示数字? Thanks for the help. 谢谢您的帮助。 :) :)

Just a suggestion, if you would like to make a little more robust form of your persistent info, you might consider object serialization. 只是一个建议,如果您想对持久性信息进行更健壮的形式,则可以考虑对象序列化。 It's easier than it sounds. 这比听起来容易。 Just have a static inner class that implements Serializable, something like this: 只是有一个实现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);
    }
}

Now, one method to store a 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();
    }
}

Another method to restore a JunkRec, given the filename. 给定文件名,还原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;
}

And finally a little test driver in main()... 最后是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();
    }
}

This is not production-quality code, but it shows how easy serialization can be. 这不是生产质量的代码,但是它显示了序列化有多么容易。 There are a gotchas, but in general Serialization is a solid solution for file-based persistence. 有一个陷阱,但是总的来说,序列化是基于文件的持久性的可靠解决方案。

Just a suggestion. 只是一个建议。 Have fun! 玩得开心!

The write method writes a single character, so you're writing characters with the Unicode codepoint of blockID, blockX, blockY which is not what you want. write方法只写一个字符,因此您要用的Unicode代码点为blockID,blockX,blockY来编写字符,而这并不是您想要的。

Whether your Writer is encoded as UTF-8 is not so relevant here, although it is always good to be explicit about encoding if you want your files to be portable across machines, so try new OutputStreamWriter(new FileOutputStream("res/save/" + filePath+ fileName, true), "UTF-8"); 是否将Writer编码为UTF-8并不是很重要,尽管如果希望文件在计算机之间可移植,最好明确地进行编码,因此请尝试使用new OutputStreamWriter(new FileOutputStream("res/save/" + filePath+ fileName, true), "UTF-8"); instead of creating a FileWriter directly. 而不是直接创建FileWriter。 Creating it directly doesn't allow you to specify the encoding. 直接创建它不允许您指定编码。

Instead do something like this: 而是这样做:

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

This will format your three numbers as one string on one line before sending it to the file. 这会将三个数字格式化为一行上的一个字符串,然后再发送到文件中。

Note that you shouldn't create a new Writer/BufferedWriter every time that you want to write a line. 请注意,不应在每次要写一行时都创建一个新的Writer / BufferedWriter。 You should keep them in a class field and re-use the same writer. 您应该将它们保留在class字段中,然后重用同一位作家。 You also need to close the file after you are done with it, since the operating system has a limit to the number of files that you have open at the same time, and you will run out of that number quickly with your current code. 完成操作后,您还需要关闭文件,因为操作系统对同时打开的文件数量有限制,并且您的当前代码很快就会用完该数量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM