【问题标题】:Java: Check if a string could be properly encoded using given charset?Java:检查字符串是否可以使用给定的字符集正确编码?
【发布时间】:2019-07-16 16:26:37
【问题描述】:

如何检查字符串是否可以用给定的字符集正确编码(不丢失信息)?

显而易见的方法是转换为目标编码,解码回来并进行比较。有没有更聪明的方法?

P.S. 实际应用是对大型文本文件使用 8 位编码,过滤掉给定字符集无法编码的字符串。 (如果需要,它们可以保存在单独的 UTF-8 文件中)。

简单的解决方案:

import java.nio.charset.Charset;

public class NaiveCharsetValidatation {
    public static void main(String[] args) {
        Charset targetCharset = Charset.forName("iso-8859-1");

        byte[] bytes = "ภาษาไทย".getBytes(targetCharset);

        String decodedString = new String(bytes, targetCharset);

        System.out.println(decodedString); // outputs ???????
    }
}

【问题讨论】:

  • @JonK 请检查解决方案(添加到原帖中)。
  • @JonK,他的建议可以正常工作(即使他正在寻找更快的东西)。当您第一次转换为目标编码时,在该编码中没有表示的任何字符都将丢失或变成某种缺失字符标记(如“?”或 �)。之后转换回原始编码时,字符串肯定不会再匹配了。

标签: java encoding character-encoding


【解决方案1】:

对于任何编码到任何其他编码的一般情况,您提出的方法是最直接的方法。但是,如果您知道易于测试的属性,则可以更快地完成测试。例如,如果您想编码为 ISO-88591-1,您可以简单地查找代码点大于 0xFF 的任何字符。对于 ASCII,任何大于 0x7F 的代码点。

一个简单的正则表达式就可以完成这种测试。您还可以使用正则表达式来测试多个字符范围,如果它很容易找到一些不会翻译的代码点跨度。

如果这个正则表达式为真:

/[^\x00-\xFF]/

任何匹配的字符串都不能无损地转换为 ISO-8859-1。

对于 Java,那就是 Pattern.compile("[^\\x00-\\xFF]")

(我已经不再使用 Java,而是使用 TypeScript/JavaScript 这么久了,我不再习惯 Java 正则表达式语法了!)

【讨论】:

    【解决方案2】:

    您可以通过尝试编码/解码来检查字符串是否可以在特定的字符编码中正确表示。

    例如:

    import java.io.UnsupportedEncodingException;
    
    class Main {
      public static void main(String[] args) throws UnsupportedEncodingException {
        if (canBeConvertedToStringEncoding("abc", "ISO-8859-1")) {
          System.out.println("can be converted");
        } else {
          System.out.println("cannot be converted");
        }
    
        if (canBeConvertedToStringEncoding("あいう", "ISO-8859-1")) {
          System.out.println("can be converted");
        } else {
          System.out.println("cannot be converted");
        }
      }
    
      public static boolean canBeConvertedToStringEncoding(String target, String encoding) throws UnsupportedEncodingException {
        String to = new String(target.getBytes(encoding), encoding);
        if (target.equals(to)) {
          return true;
        } else {
          return false;
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-17
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多