1


我正在编写一个应该检测使用过的字符集然后将其切换为 utf-8 的函数。我正在使用 juniversalchardet,它是 mozilla 的 Universalchardet 的 Java 端口。
这是我的代码:

private List<List<String>> setProperEncoding(List<List<String>> input) {
    try {

        // Detect used charset
        UniversalDetector detector = new UniversalDetector(null);

        int position = 0;
        while ((position < input.size()) & (!detector.isDone())) {
            String row = null;
            for (String cell : input.get(position)) {
                row += cell;
            }
            byte[] bytes = row.getBytes();
            detector.handleData(bytes, 0, bytes.length);
            position++;
        }
        detector.dataEnd();

        Charset charset = Charset.forName(detector.getDetectedCharset());
        Charset utf8 = Charset.forName("UTF-8");
        System.out.println("Detected charset: " + charset);

        // rewrite input using proper charset
        List<List<String>> newLines = new ArrayList<List<String>>();
        for (List<String> row : input) {
            List<String> newRow = new ArrayList<String>();
            for (String cell : row) {
                //newRow.add(new String(cell.getBytes(charset)));
                ByteBuffer bb = ByteBuffer.wrap(cell.getBytes(charset));
                CharBuffer cb = charset.decode(bb);
                bb = utf8.encode(cb);
                newRow.add(new String(bb.array()));
            }
            newLines.add(newRow);
        }

        return newLines;

    } catch (Exception e) {
        e.printStackTrace();
        return input;
    }
}

我的问题是,当我读取带有波兰字母等字符的文件时,像 ł、ą、ć 和类似的字母会被替换为 ? 和其他奇怪的事情。我究竟做错了什么?

编辑:对于编译,我使用的是 eclipse。

方法参数是读取 MultipartFile 的结果。只需使用 FileInputStream 获取每一行,然后用某个分隔符分割每一行(它已为 xls、xlsx 和 csv 文件准备好)。那里没什么特别的。

4

1 回答 1

1

首先,你的数据是二进制格式的。为了简单起见,我想它来自一个InputStream.

你想把输出写成一个UTF-8字符串,我想它可以是一个 OutputStream。

我建议创建一个AutoDetectInputStream

public class AutoDetectInputStream extends InputStream  {
    private InputStream is;
    private byte[] sampleData = new byte[4096];
    private int sampleLen;
    private int sampleIndex = 0;

    public AutoDetectStream(InputStream is) throws IOException {
        this.is = is;
        // pre-read the data
        sampleLen = is.read(sampleData);
    }

    public Charset getCharset() {
        // detect the charset
        UniversalDetector detector = new UniversalDetector(null);
        detector.handleData(sampleData, 0, sampleLen);
        detector.dataEnd();
        return detector.getDetectedCharset();
    }

    @Override
    public int read() throws IOException {
        // simulate the stream for the reader
        if(sampleIndex < sampleLen) {
            return sampleData[sampleIndex++];
        }
        return is.read();
    }
}

第二个任务非常简单,因为 Java 将字符串(字符)存储在 中UTF-8,所以只需使用一个简单的 OutputStreamWriter。所以,这是你的代码:

// open input with Detector stream
// we use BufferedReader so we could read lines
InputStream is = new FileInputStream("in.txt");
AutoDetectInputStream detector = new AutoDetectInputStream(is);
Charset charset = detector.getCharset();
// here we can use the charset to decode the bytes into characters
BufferedReader rdr = new BufferedReader(new InputStreamReader(detector, charset));

// open output to write to
OutputStream os = new FileOutputStream("out.txt");
Writer utf8Writer = new OutputStreamWriter(os, Charset.forName("UTF-8"));

// copy the whole file
String line;
while((line = rdr.readLine()) != null) {
    utf8Writer.append(line);
}

// close streams        
rdr.close();
utf8Writer.flush();
utf8Writer.close();

因此,最后您将所有 txt 文件转码为 UTF-8。

请注意,缓冲区大小应该足够大以提供UniversalDetector.

于 2013-07-16T16:41:18.237 回答