如何解析与java编码不同的字符串

如何解析与java编码不同的字符串,java,character-encoding,Java,Character Encoding,我有一个从Word文档中读入的字符串。我想它是用“Cp1252”编码的。Java使用UTF8 如何在Cp1252中搜索该字符串中的特殊字符,并将其替换为适当的UTF8字符 具体来说,我想用一个简单的“-”替换“En-Dash”字符 下面的代码块获取来自Word文档的projDateString,并尝试执行这样的操作 char[] test = projDateString.getBytes("Cp1252"); for(int i = 0; i < test.length;

我有一个从Word文档中读入的字符串。我想它是用“Cp1252”编码的。Java使用UTF8

如何在Cp1252中搜索该字符串中的特殊字符,并将其替换为适当的UTF8字符

具体来说,我想用一个简单的“-”替换“En-Dash”字符

下面的代码块获取来自Word文档的projDateString,并尝试执行这样的操作

    char[] test = projDateString.getBytes("Cp1252");
    for(int i = 0; i < test.length; i++){
    System.out.println "test["+ i + "] = " + Integer.toHexString((byte)test[i]);
    }
    String projDateString2 = new String(test);
    projDateString2.replaceAll("\0x96", "\u2013");
    System.out.println("projDateString2: " + projDateString)

正如您所看到的,replace什么也没做,println仍然给我垃圾字符,而不是纯文本“-”

转换通常是这样完成的:

String properlyEncoded = 
    new String(original.getBytes(originalEncoding), newEncoding);

请注意,在转换过程中某些信息不太可能丢失。

转换通常通过以下方式完成:

String properlyEncoded = 
    new String(original.getBytes(originalEncoding), newEncoding);
请注意,在转换过程中某些信息丢失的可能性不大。

Java字符串始终在UTF-16中,至少就API而言。。。但您通常可以将它们看作是“Unicode”。事实上,它们是UTF-16,只有在涉及基本多语言平面之外的字符时才真正相关,即Unicode值高于U+FFFF。它们必须在Java中表示为代理项对。但我认为你不必担心你的情况。所以只要把字符串中的值想象成“Unicode文本”,而不使用特定的编码。。。特别是,在UTF-8或CP1252中绝对不是。这些是用于将二进制数据(例如字节数组)转换为文本数据(例如字符串)的编码

如果不指定编码,就不应该使用
String.getBytes()
新字符串(byte[])
,这就是问题所在。他们总是使用平台默认编码——这几乎总是错误的选择

你说你“有一个我从Word文档中读入的字符串”-你是怎么读入的?它是如何开始生活的

如果您有字节并且知道相关编码,则应使用:

String text = new String(bytes, encoding);
您永远不应该处理使用错误编码创建的字符串-如果您达到该阶段,您几乎肯定会面临信息丢失的风险。尽可能早地解决问题,而不是稍后尝试修复数据

接下来要了解的是Java中的
String
类是不可变的。对字符串调用
replaceAll
,不会更改现有字符串。它将返回一个新字符串,其中包含替换内容

因此,这项声明:

projDateString2.replaceAll("\0x96", "\u2013");
我永远不会做你想做的事。即使其他一切都是正确的,您也应该使用:

projDateString2 = projDateString2.replaceAll("\0x96", "\u2013");
(或类似的东西)。我不认为这实际上会满足您的要求,但您需要知道,当所有其他事情都解决后,Java字符串总是在UTF-16中,至少就API而言。。。但您通常可以将它们看作是“Unicode”。事实上,它们是UTF-16,只有在涉及基本多语言平面之外的字符时才真正相关,即Unicode值高于U+FFFF。它们必须在Java中表示为代理项对。但我认为你不必担心你的情况。所以只要把字符串中的值想象成“Unicode文本”,而不使用特定的编码。。。特别是,在UTF-8或CP1252中绝对不是。这些是用于将二进制数据(例如字节数组)转换为文本数据(例如字符串)的编码

如果不指定编码,就不应该使用
String.getBytes()
新字符串(byte[])
,这就是问题所在。他们总是使用平台默认编码——这几乎总是错误的选择

你说你“有一个我从Word文档中读入的字符串”-你是怎么读入的?它是如何开始生活的

如果您有字节并且知道相关编码,则应使用:

String text = new String(bytes, encoding);
您永远不应该处理使用错误编码创建的字符串-如果您达到该阶段,您几乎肯定会面临信息丢失的风险。尽可能早地解决问题,而不是稍后尝试修复数据

接下来要了解的是Java中的
String
类是不可变的。对字符串调用
replaceAll
,不会更改现有字符串。它将返回一个新字符串,其中包含替换内容

因此,这项声明:

projDateString2.replaceAll("\0x96", "\u2013");
我永远不会做你想做的事。即使其他一切都是正确的,您也应该使用:

projDateString2 = projDateString2.replaceAll("\0x96", "\u2013");

(或类似的东西)。我不认为这真的能满足你的需要,但你需要在其他事情都解决后意识到这一点。

首先,你需要确保正确地将CP1252字节转换为Java字节(即UTF-16)。因为您正在使用一个库来解析.docx文件,所以可能已经发生了这种情况


现在只需调用
projDateString.replace('\u2013','-')
并使用返回值执行一些操作。无需使用
replaceAll()
,因为您没有使用正则表达式。

首先,您需要确保正确地将CP1252字节转换为Java字节(即UTF-16)。因为您正在使用一个库来解析.docx文件,所以可能已经发生了这种情况


现在只需调用
projDateString.replace('\u2013','-')
并使用返回值执行一些操作。不需要使用
replaceAll()
,因为您没有使用正则表达式。

好的,所以我使用了字符串projDateString2=新字符串(projDateString.getBytes(“Cp1252”),“UTF-16”);而且我仍然无法使replaceAll正确工作,尽管转换很容易有损,因为原始的不正确转换很容易丢失信息。@Jon Skeet true。但我认为,您无法防止丢失。好吧,我做了String projDateString2=新字符串(projDateString.getBytes(“Cp1252”),“UTF-16”);我还是不能