【问题标题】:Convert Windows-1252 to UTF-16 in Java在 Java 中将 Windows-1252 转换为 UTF-16
【发布时间】:2012-09-27 21:11:50
【问题描述】:

我正在尝试将所有 Windows 特殊字符转换为它们的 Unicode 等效字符。我们有一个 Flex 应用程序,用户在其中保存一些富文本,然后通过 Java 电子邮件程序将其通过电子邮件发送给他们的收件人。但是,我们不断遇到 Word 的特殊字符,这些字符仅在电子邮件中显示为 ?。

到目前为止我已经尝试过

 private String replaceWordChars(String text_in) {
    String s = text_in;

    // smart single quotes and apostrophe
    s = s.replaceAll("[\\u2018|\\u2019|\\u201A]", "\'");
    // smart double quotes
    s = s.replaceAll("[\\u201C|\\u201D|\\u201E]", "\"");
    // ellipsis
    s = s.replaceAll("\\u2026", "...");
    // dashes
    s = s.replaceAll("[\\u2013|\\u2014]", "-");
    // circumflex
    s = s.replaceAll("\\u02C6", "^");
    // open angle bracket
    s = s.replaceAll("\\u2039", "<");
    // close angle bracket
    s = s.replaceAll("\\u203A", ">");
    // spaces
    s = s.replaceAll("[\\u02DC|\\u00A0]", " ");

    return s;

这可行,但我不想将所有 Windows-1252 字符手动编码为等效的 UTF-16(假设这是默认 Java 字符集)

但是,我们的用户不断从 Microsoft Word 中发现更多 Java 无法处理的字符。于是找了找,找到了这个例子

private String replaceWordChars(String text_in) {
    String s = text_in;
    try {
        byte[] b = s.getBytes("Cp1252");
        byte[] encoded = new String(b, "Cp1252").getBytes("UTF-16");
        s = new String(encoded, "UTF-16");


    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return s;

但是当我在 Eclipse 调试器中看到编码发生时,没有任何变化。

必须有一个简单的解决方案来处理微软可爱的 Java 编码。

有什么想法吗?

【问题讨论】:

  • 在第一种情况下,您只是用 ASCII 字符替换非 ASCII 字符。你根本没有改变 encoding 。在第二段代码中,除了将 Cp1252 无法处理的所有字符转换为“?”之外,您实际上什么也没做。
  • 好的 @JonSkeet 有没有想过用它们的 ASCII 等效字符替换所有非 ASCII 字符?
  • @CodingGuy 并非所有非 ascii 字符都有 ascii 等价物……ASCII 少于 128 个字符,而 Unicode 字符超过 100,000 个。您只需要弄清楚如何正确发送电子邮件。发送的电子邮件是什么编码?它应该是 UTF-8,然后您就不必删除非 ascii 字符了。
  • emailer 确实使用 UTF-8,当它不知道字符时,例如子弹,电子邮件只包含一个可爱的?。
  • 那么电子邮件生成器或生成电子邮件文本的程序有其他问题,因为没有理由将特殊字符转换为 ?在 UTF-8 电子邮件中。

标签: java eclipse apache-flex


【解决方案1】:

你可以试试java.nio.charset.Charset:

final Charset windowsCharset = Charset.forName("windows-1252");
final Charset utfCharset = Charset.forName("UTF-16");
final CharBuffer windowsEncoded = windowsCharset.decode(ByteBuffer.wrap(new byte[] {(byte) 0x91}));
final byte[] utfEncoded = utfCharset.encode(windowsEncoded).array();
System.out.println(new String(utfEncoded, utfCharset.displayName()));

【讨论】:

    【解决方案2】:

    使用以下步骤:

    1. 使用源文件的编码 (Windows-1252) 创建 InputStreamReader
    2. 使用目标文件的编码 (UTF-16) 创建 OutputStreamWriter
    3. 将从读取器读取的信息复制到写入器。您可以使用BufferedReaderBufferedWriter 逐行编写内容。

    所以您的代码可能如下所示:

    public void reencode(InputStream source, OutputStream dest,
            String sourceEncoding, String destEncoding)
            throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(source, sourceEncoding));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, destEncoding));
        String in;
        while ((in = reader.readLine()) != null) {
            writer.write(in);
            writer.newLine();
        }
    }
    

    当然,这不包括 try/catch 内容并将其委托给调用者。

    如果您只是想以字符串的形式获取内容,您可以将writer 替换为StringWriter 并返回其toString 值。那么你不需要目标流或编码,只需要一个转储字符的地方:

    public String decode(InputStream source, String sourceEncoding)
            throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(source, sourceEncoding));
        StringWriter writer = new StringWriter();
        String in;
        while ((in = reader.readLine()) != null) {
            writer.write(in);
            writer.write('\n'); // Java newline should be fine, test this just in case
        }
        return writer.toString();
    }
    

    【讨论】:

    • 为什么投反对票?没有代码?现在就写吧。请先评论,稍后投反对票。
    • 第 1 步不起作用。这来自网络上的 Flex RIA。用户很可能会用 word 输入他们漂亮的电子邮件,然后复制粘贴到我们的应用程序中并启动电子邮件。我会试试 Streams 看看会发生什么。
    • 我刚刚推荐了它。我正在编写的代码实际上只是使用流。一切都好。我会将它包含在我的编辑中。
    • 我没有投反对票,这个词似乎适用于桌面应用程序?
    • 很公平。请查看我的更新 :) 这应该让您知道从哪里开始。
    【解决方案3】:

    到目前为止,我测试过的所有东西似乎都有效的是:

    private String replaceWordChars(String text_in) {
        String s = text_in;
        
        final Charset windowsCharset = Charset.forName("windows-1252");
        final Charset utfCharset     = Charset.forName("UTF-16");
        
        byte[] incomingBytes = s.getBytes();
        final CharBuffer windowsEncoded = 
            windowsCharset.decode(ByteBuffer.wrap(incomingBytes)); 
        
        final byte[] utfEncoded = utfCharset.encode(windowsEncoded).array();
        s = new String(utfEncoded);
        
        return s;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-09
      • 2019-08-19
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 2017-09-24
      • 1970-01-01
      • 2016-07-23
      相关资源
      最近更新 更多