2

我需要将文件从 UTF-8 编码为 Shift_JIS。以前,这是使用 iconv 命令完成的,如下所示

iconv -f utf8 -t sjis $INPUT_FILE 

我提供的输入文件返回一个错误,说

位置 2551 处的非法输入序列

我写了这段Java代码:

FileInputStream fis = new FileInputStream(
        "Input.txt");
InputStreamReader in = new InputStreamReader(fis, "UTF-8");
FileOutputStream fos = new FileOutputStream("Output.txt");
OutputStreamWriter out = new OutputStreamWriter(fos, "Shift_JIS");

        int val = 0;
        StringBuilder sb = new StringBuilder();

        while((val =in.read() )!= -1){
            System.out.println(Integer.toHexString(val));
            sb.append((char)val);
        }
        out.write(sb.toString());
        out.flush();
        fis.close();
        out.close();

该代码使用相同的输入文件执行良好,并且不返回任何错误。

我在这里错过了什么吗?

约阿希姆。这看起来像答案。我在问题中添加了我的代码。我现在收到不可映射的字符错误。但它无法像任何文本“hello”那样对普通字符进行编码。我在任何地方都做错了吗

    private static CharsetDecoder decoder(String encoding) {
        return Charset.forName(encoding).newDecoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT);
    }

    private static CharsetEncoder encoder(String encoding) {
        return Charset.forName(encoding).newEncoder()
            .onMalformedInput(CodingErrorAction.REPORT)
            .onUnmappableCharacter(CodingErrorAction.REPORT);
    }

    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream(
        "D:\\Input.txt");
InputStreamReader in = new InputStreamReader(fis, decoder("UTF-8"));
FileOutputStream fos = new FileOutputStream("D:\\Output.txt");
OutputStreamWriter out = new OutputStreamWriter(fos, encoder("Shift_JIS"));
        char[] buffer = new char[4096];
        int length;

        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }

        out.flush();
    }
4

1 回答 1

2

这应该只是一个关于 UTF-8 的问题。只需执行 InputStream 并从位置 2551 开始十六进制转储,或者前面的文本更早一点。

特别有趣的是,iconv 在那里提供了什么。


转储:

所以我们可以看到是哪些数据导致了问题。

public static void main(String[] args) {
    try (BufferedInputStream in = new BufferedInputStream(
            new FileInputStream("D:\\input.txt"))) {
        dumpBytes(in, 2551 - 10, 20);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

private static void dumpBytes(InputStream in, long offset, int length)
        throws IOException {
    long pos = in.skip(offset);
    while (length >= 0) {
        int b = in.read();
        if (b == -1) {
            break;
        }
        b &= 0xFF;
        System.out.printf("%6d: 0x%02x %s '%c'%n", pos, b,
            toBinaryString(b), (32 <= b && b < 127 ? (char)b : '?'));

        --length;
        ++pos;
    }
}

private static String toBinaryString(int b) {
    String s = Integer.toBinaryString(b);
    s = "00000000" + s;
    s = s.substring(s.length() - 8);
    s = s.substring(0, 4) + "_" + s.substring(4);
    return s;
}
于 2013-05-02T13:26:47.167 回答