Java中的iconv等效代码不';我不能返回相同的结果

Java中的iconv等效代码不';我不能返回相同的结果,java,encoding,iconv,Java,Encoding,Iconv,我需要将文件从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-

我需要将文件从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();
    }

这应该只是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;
}
publicstaticvoidmain(字符串[]args){
try(BufferedInputStream in=new BufferedInputStream)(
新文件输入流(“D:\\input.txt”)){
转储字节(in,2551-10,20);
}捕获(IOEX异常){
例如printStackTrace();
}
}
专用静态void dumpBytes(InputStream-in、long offset、int-length)
抛出IOException{
长位置=英寸跳跃(偏移);
while(长度>=0){
int b=in.read();
如果(b==-1){
打破
}
b&=0xFF;
System.out.printf(“%6d:0x%02x%s”%c“%n”,位置,b,

toBinaryString(b),(32)我不确定tat会有什么帮助。你能解释一下吗?这不是获得分数的解决方案,但2551处的字节序列必须是损坏的UTF-8(“非法输入序列”).知道字节/位,就可以很容易地看出这是否确实是非法的UTF-8,也许还可以从中扣除原因。@Joop.我已经得到了hextump,但无法理解您的语句“知道字节/位,就可以很容易地看出这是否确实是非法的UTF-8”。你能解释一下吗。我对编码和十六进制结构非常陌生。我添加了一个dumpBytes,这样我们可以看到有问题的数据。得到十六进制转储,可以找到问题区域,谢谢你提供的信息