【问题标题】:Java How to write a string in file as bytes and get string backJava如何将文件中的字符串作为字节写入并取回字符串
【发布时间】:2014-10-08 21:36:14
【问题描述】:

我需要将一个字符串作为 UTF-8 中的字节写入文件中,然后从文件中取回这些字节并将其转换回字符串,然后得到相同的字符串。可能听起来很简单,但有一个隐藏的问题,例如文件中的符号不​​正确。我的意思是,在附加到文件之后,它必须包含以下内容:

00000008 d0bad0bb d18ed187 00000010 等...

但它包含类似的东西:

mystring ---很多空间---(以及这里没有显示的符号)

那么,我已经做了什么?我试过这种方式:

在代码阅读之前:我将字符串保存在 HashMap 这就是为什么我的代码包含 get(...) 等。

try {
        FileOutputStream oStream = new FileOutputStream("filename.txt");
        Set<String> keySet = storage.keySet();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        for (String key : keySet) {
            byte[] keyInByte = key.getBytes("UTF-8");
            byte[] valueInByte = storage.get(key).getBytes("UTF-8");
            oStream.write(buffer.putInt(0, valueInByte.length).array());
            oStream.write(keyInByte);

            oStream.write((buffer.putInt(0, valueInByte.length).array()));
            oStream.write(valueInByte);
        }
    } catch (Exception e) {
        System.err.println("permission denied");
    }

我也尝试过使用 PrintWriter、FileWriter 等...但它没有提供我需要的东西。例如,其中一些需要 toString() 方法,但在 toString() 之后我将失去处理字节的能力。

!请注意,我尝试将记事本更改为 UTF-8 编码,但没有给出任何结果。

【问题讨论】:

  • 为什么不使用 PrintWriter 和 BufferedReader 因为文件最终总是字节。它们会更简单,而且可能更快。通常.txt 表示文本不是二进制的。 BTW DataInput/OuputStream 作为 writeUTF/readUTF 方法可以更有效地执行此类操作。
  • @PeterLawrey 正如我所提到的,我已经尝试了很多方法,包括 PrintWriter,它需要使用 toString() 方法进行我的操作。那么我将失去正确处理字节的能力。
  • 不知道为什么你不能用 Reader/Writer 做到这一点。从您的描述看来,您的问题是您使用的是二进制而不是文本。但如果你需要二进制格式,你可以使用数据流。
  • @PeterLawrey 你能写一些代码吗?可能有一个我不明白的解决方案......
  • 具体示例取决于您的要求,例如,我不会将长度写入文本文件,而只会写入二进制文件。写入长度会使编辑文件变得难以编辑。 (使用二进制格式编辑文件不是一种选择)我也不清楚你想要文本还是二进制。顺便说一句,您应该始终打印出异常,因为可能有很多原因。

标签: java string file utf-8


【解决方案1】:

如果你想使用属性,你可以这样做。

new Properties(map).save(new FileOutputStream("filename.proeprties"));

加载属性

Properties prop = new Properties();
prop.load(new FileInputStream("filename.properties"));
map.putAll(prop);

要保存复制数据,您可以将属性用作地图。

key1=value1
key2=value2

注意:键不能包含= 或换行符。


这就是我将以二进制格式执行的操作

DataOutputStream dos = new BufferedOutputStream(new FileOutputStream("filename.dat")));
dos.writeInt(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
    dos.writeUTF(entry.getKey());
    dos.writeUTF(entry.getValue());
}
dos.close();

这就是我使用 UTF-8 以文本形式编写它的方式

PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOuputStream("filename.txt") "UTF-8"));
pw.println(map.size());
for (Map.Entry<String, String> entry : map.entrySet()) {
     pw.println(encode(entry.getKey()));
     pw.println(encode(entry.getValue()));
}
pw.close();


public static String encode(String s) {
    // if you can assume no new lines, don't do anything.
    return s.replaceAll("\\\\", "\\\\\\\\").replaceAll("\n", "\\\\n");
}

这会产生一个赞

key1
value1
key2
value2

这个你可以很容易地编辑。如果您假设密钥没有=: 或制表符,您可以像属性文件一样使用一行

【讨论】:

  • 谢谢!你真的帮了我。但我还有一个问题:return s.replaceAll("\\", "\\\\").replaceAll("\n", "\\n"); 因为“\\”和“\\\\”而不起作用。我应该改用“//”吗?顺便说一句,如果这很重要,我会在 Windows 8.1 上使用 intellij IDEA =) 对于愚蠢的问题,我很抱歉,我只是 Java 的新手。
  • 你的意思是它不起作用?顺便说一句,我在 win 8.1 上也有 intellij。
  • @PeterLawrey 我猜“不起作用”的意思是“抛出异常”,因为replaceAll 使用正则表达式作为参数,@987654332 @ 在 Java 中是不正确的正则表达式(就像将 \ 写成正则表达式一样,这是错误的,因为 \ 在它之后需要像 \s\d\\ 这样的东西)。也许您想使用replace 而不是replaceAll
  • replaceAll("\\\\", "\\\\") 没有意义 :/ (你用一个\ 替换一个\ 因为\ 在替换部分也很特殊-它可以与"\\$" 一起使用来表示$ 文字,因为 $ 本身也很特殊,因为它可以像 "$1" 一样使用,让我们在存储在组 1 中的替换匹配中使用。如果您想用两个\\ 替换一个\,请使用replaceAll("\\\\", "\\\\\\\\") 或避免正则表达式混淆replace("\\","\\\\")
  • 是的,第二个参数是字符串,但这个参数不只是任何字符串,因为它也被正则表达式引擎在替换时使用,并且可以包含一些特殊字符,即$ - 参考匹配正则表达式匹配的组(例如,$1 表示来自组 1 的匹配),\ 让我们转义$,因此要在第二个参数中表示\ 文字,您需要将其写为"\\\\" .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
相关资源
最近更新 更多