在java中,将字符串从一种编码解释为另一种编码

在java中,将字符串从一种编码解释为另一种编码,java,string,encoding,utf-8,Java,String,Encoding,Utf 8,我已经四处寻找答案(我肯定他们在那里),但我不确定这是可能的 所以,我得到了一个包含“för”这个词的巨大文件。我使用RandomAccessFile是因为我知道它在哪里(某种程度上),因此可以使用seek()函数到达那里 为了知道我找到了它,我在程序中有一个字符串“för”,我检查它是否相等。问题是,我运行了调试器,当我到达“för”时,我要比较的是“för” 因此,我的程序终止时没有找到任何“för” 这是我用来获取单词的代码: private static String getWo

我已经四处寻找答案(我肯定他们在那里),但我不确定这是可能的

所以,我得到了一个包含“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”

您正在使用。它读取单个字节。UTF-8有时对一个字符使用几个字节

这里讨论了从RandomAccessFile读取UTF-8的不同方法:

如果您不一定需要RandomAccessFile,那么您肯定应该切换到读取字符而不是字节


如果可能,我建议默认情况下搜索下一个单词。

如果必须使用
随机访问文件
,则应首先将内容读入
字节[]
,然后将整个数组转换为
字符串
-如下所示:

byte[] buffer = new byte[whatever];
file.read(buffer);
String result = new String(buffer,"UTF-8");
这只是给你一个大致的印象,你要做什么,你必须添加一些长度处理等


如果你在UTF-8序列中开始阅读,这将无法正常工作,但是任何其他方法都会正确。

在一些Google(几秒钟前)之后,我设法实现了看起来像是一个解决方案。基本上是:byte[]utf8Bytes=theWord.getBytes(“ISO-8859-1”);然后单词=新字符串(utf8Bytes,“UTF8”);。这个词现在已经从“för”变成了“för”。这样或那样做有什么原因吗?只是好奇:)PS我刚刚实现了你的解决方案,它也解决了问题,所以我接受你的回答。我和你的解决方案是一样的。唯一的区别是,我的解决方案是一行。ISO-8859-15不会将代码中非常糟糕的
字节
转换为
字符
转换。虽然在这种情况下可能会起作用,但在将某个内容转换为
字符串
后转换编码肯定会给您带来麻烦,因为在转换过程中可能已经丢失了信息
字节
字符串
的第一次转换。唯一正确处理编码问题的地方是在读/写时。@piet.t我同意,但作者问的是如何将字符串从一种编码转换为另一种编码。您的问题就在这里:
(char)file.read()
。该方法不返回
字符
。它返回一个
字节
。不要将
字节
强制转换为
字符
——为什么您使用的是
RandomAccessFile
,而不是更有用的
FileReader
,可以自动将字节转换为字符?@Andreas RandomAccessFile具有seek(long pos)功能允许我在文件中跳过X个字节,而不打开和读取前面的内容。但是搜索可能会使你处于UTF-8序列的中间,那么你如何决定去哪里寻找?在UTF-8中,字符占用可变的字节数,因此除非您读取它们,否则无法知道要跳过多少字节。我认为OP已经得到了足够的警告。我们不能帮助每个想自己进行编码或时区计算的人。“我想,人们必须以艰苦的方式吸取教训。”安德烈亚斯非常感谢你的帮助。恐怕这是一个大文件,我必须在很短的时间内搜索它,这意味着我必须使用seek(long pos)。你绝对是对的,因为这可能使我处于UTF-8序列的中间,所以我现在所看到的是在ISO-859-1中写下我正在看的文件(这是我的程序之前所做的)(这样每个字符都是一个字节)这样我就可以有效地使用seek方法了。@Andreas如果性能有问题,你应该远离
扫描仪。
byte[] buffer = new byte[whatever];
file.read(buffer);
String result = new String(buffer,"UTF-8");