读写ISO-8859-1编码的文件?

问题描述

我有按ISO-8859-1编码的文件。我试图以单个String的形式读取它,对其进行一些正则表达式替换,并以相同的编码写回。

但是,我得到的结果文件似乎始终是UTF-8(至少根据Notepad ++而言),其中包含一些字符。

有人在这里看到我在做什么错吗?

private static void editFile(File source,File target) {

    // Source and target encoding
    Charset iso88591charset = Charset.forName("ISO-8859-1");

    // Read the file as a single string
    String fileContent = null;

    try (Scanner scanner = new Scanner(source,iso88591charset)) {
    
        fileContent = scanner.useDelimiter("\\Z").next();
                
    } catch (IOException exception) {
        LOGGER.error("Could not read input file as a single String.",exception);
        return;
    }

    // Do some regex substitutions on the fileContent string
    String newContent = regex(fileContent);

    // Write the file back out in target encoding
    try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target),iso88591charset))) {
    
        writer.write(newContent);
        
    } catch (Exception exception) {
        LOGGER.error("Could not write out edited file!",exception);
    }
}

解决方法

您的代码实际上没有任何错误。 Notepad ++可以看到使用UTF-8编码的文件,因为在基本级别上,UTF-8和您尝试使用的编码之间没有区别。与UTF相比,仅特定字符有所不同,ISO中缺少某些(很多)字符。您可以阅读更多here,也可以在Google中搜索ISO-8859-1 vs UTF-8

I've created a simple project with your code并使用与ISO编码不同的字符对其进行了测试-结果是IntelliJ(可能还包括Notepad ++-无法轻易检查,我在Linux上)识别为ISO-8859的文件-1。除此之外,我还添加了另一个类,该类利用Files类中的新(JDK11)功能。您使用的new Scanner(source,charset)已添加到JDK10中,所以我认为您可能已经在使用11。这是简化的代码:

private static void editFile(File source,File target) {
    Charset charset = StandardCharsets.ISO_8859_1;
    String fileContent;
    try {
        fileContent = Files.readString(source.toPath(),charset);
    } catch (IOException exception) {
        System.err.println("Could not read input file as a single String.");
        exception.printStackTrace();
        return;
    }
    String newContent = regex(fileContent);
    try {
        Files.writeString(target.toPath(),newContent,charset);
    } catch (IOException exception) {
        System.err.println("Could not write out edited file!");
        exception.printStackTrace();
    }
}

可以随时克隆存储库或在GitHub上进行检查,并使用您喜欢的任何代码版本。