在 Java 中将字符串从一种编码转换为另一种编码

4

我找过答案了(我相信它们在那里),但我不确定是否可能。

所以,我得到了一个包含单词“för”的巨大文件。我正在使用RandomAccessFile,因为我知道它在哪里(有点)并且因此可以使用seek()函数到达那里。

为了知道我已经找到它,我在程序中有一个字符串“för”,我检查它是否相等。问题在于,当我到达“för”时,我得到的比较对象是"för"。

因此,我的程序在没有找到任何“för”的情况下终止。

这是我用来获取单词的代码:

    private static String getWord(RandomAccessFile file) throws IOException {
    StringBuilder stb = new StringBuilder();
    String word;
    char c;
    c = (char)file.read();
    int end;
    do {
        stb.append(c);
        end = file.read();
        if(end==-1)
            return "-1";
        c = (char)end;

    } while (c != ' ');
    word = stb.toString();
    word.trim();
    return word;
}

基本上,我将从文件中的当前点返回所有字符到第一个“-”字符。所以我基本上获取了这个单词,但由于(char) file.read();读取一个字节(我想),UTF-8 'ö'成为两个字符'Ã'和'¶'?

猜测其中一个原因是,如果我使用UTF-8编码打开文件,它是“för”,但如果我在同一位置使用ISO-8859-15打开文件,则现在正好有我的getWord方法返回的内容:“för”

所以我的问题是:

当我拥有“för”和“för”时,是否有任何方法可以解决这个问题?比如说,“将“för”读作UTF-8字符串”,以获取“för”?


1
你的问题就在这里:(char)file.read()read() 方法不会返回一个 char,它返回一个 byte。不要将 byte 强制转换为 char。--- 为什么不使用更有帮助的 FileReader 而是使用 RandomAccessFile,后者可以自动将字节转换为字符? - Andreas
@Andreas RandomAccessFile有一个函数seek(long pos),允许我在不打开和读取前面内容的情况下跳过文件中的X个字节。 - MrJalapeno
1
但是寻找可能会使您陷入UTF-8序列的中间,那么如何确定要寻找到哪里?在UTF-8中,字符占用可变数量的字节,因此您无法知道要跳过多少字节,除非您读取它们。 - Andreas
我认为 OP 已经受到了足够的警告。我们不能帮助每个想要自己进行编码或时区计算的人。人们必须通过艰难的方式学习教训,我想。 - Ingo Bürk
@Andreas 非常感谢您的帮助。恐怕这是一个很大的文件,我必须在非常短的时间内搜索它,这意味着我必须使用seek(long pos)。您绝对正确,事实上这可能会使我陷入UTF-8序列的中间,所以我现在正在寻找的是,也许可以将我正在查看的文件(这是我的程序在此之前执行的操作)写成ISO-8859-1格式(这样每个字符都是一个字节),这样我就可以有效地使用seek方法了。 - MrJalapeno
3个回答

3

如果你必须使用 RandomAccessFile,那么你应该先将内容读入到一个 byte[] 中,然后将整个数组转换为一个 String。以下是大致的代码示例:

byte[] buffer = new byte[whatever];
file.read(buffer);
String result = new String(buffer,"UTF-8");

这只是为了给您一个大致的印象,您需要添加一些长度处理等。

如果你在一个UTF-8序列中间开始阅读,这种方法也无法正确工作,但任何其他方法也是如此。


1

@Andreas,如果性能很重要,你应该远离Scanner - slartidan

-1
import java.nio.charset.Charset;
String encodedString = new String(originalString.getBytes("ISO-8859-15"), Charset.forName("UTF-8"));

经过一些谷歌搜索(就在几秒钟前),我成功地实现了一个看起来像解决方案的东西。基本上是:byte[] utf8Bytes = theWord.getBytes("ISO-8859-1"); 然后 **theWord = new String(utf8Bytes, "UTF8");**。theWord现在从"för"变成了"för"。这样做或那样做有什么原因吗?只是好奇 :) PS 我刚刚实现了你的解决方案,它也解决了问题,所以我会接受你的答案。 - MrJalapeno
我的解决方案和你的一样。唯一的区别是我的解决方案只有一行。 - Sergey Gornostaev
1
ISO-8859-15在代码中没有矫正非常糟糕的bytechar转换。 - Andreas
2
虽然在这种情况下将编码转换为String可能有效,但在已经将某些内容转换为String后再进行编码转换肯定会让你陷入麻烦,因为在第一次将byte转换为String时可能已经丢失了信息。处理编码问题的唯一正确位置是在读取/写入时。 - piet.t
@piet.t 我同意,但作者正在询问如何将一个字符串从一种编码转换为另一种编码。 - Sergey Gornostaev
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接