嘿伙计们,我一直在尝试解析HTML文件以从中抓取文本,而且每隔一段时间,我就会得到一些非常奇怪的字符,如à€œ
。我确定它是“智能引号”或卷曲的标点符号导致我的所有问题,所以我的临时修复是单独搜索并用相应的HTML代码替换所有这些字符。我的问题是,是否有这样一种方法可以使用一个正则表达式(或其他东西)只搜索一次字符串,并根据其中的内容替换它需要的内容?我现在的解决方案如下:
line = line.replaceAll( "“", "“" ).replaceAll( "”", "”" );
line = line.replaceAll( "–", "–" ).replaceAll( "—", "—" );
line = line.replaceAll( "‘", "‘" ).replaceAll( "’", "’" );
由于某种原因,似乎可能有更好的,可能更有效的方法来做到这一点。任何意见都非常感谢。
谢谢,
-Brett
答案 0 :(得分:3)
正如其他人所说;处理这些字符的推荐方法是配置编码设置。
为了比较,这里有一个使用正则表达式将UTF-8序列重新编码为HTML实体的方法:
import java.util.regex.*;
public class UTF8Fixer {
static String fixUTF8Characters(String str) {
// Pattern to match most UTF-8 sequences:
Pattern utf8Pattern = Pattern.compile("[\\xC0-\\xDF][\\x80-\\xBF]{1}|[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xF7][\\x80-\\xBF]{3}");
Matcher utf8Matcher = utf8Pattern.matcher(str);
StringBuffer buf = new StringBuffer();
// Search for matches
while (utf8Matcher.find()) {
// Decode the character
String encoded = utf8Matcher.group();
int codePoint = encoded.codePointAt(0);
if (codePoint >= 0xF0) {
codePoint &= 0x07;
}
else if (codePoint >= 0xE0) {
codePoint &= 0x0F;
}
else {
codePoint &= 0x1F;
}
for (int i = 1; i < encoded.length(); i++) {
codePoint = (codePoint << 6) | (encoded.codePointAt(i) & 0x3F);
}
// Recode it as an HTML entity
encoded = String.format("&#%d;", codePoint);
// Add it to the buffer
utf8Matcher.appendReplacement(buf,encoded);
}
utf8Matcher.appendTail(buf);
return buf.toString();
}
public static void main(String[] args) {
String subject = "String with \u00E2\u0080\u0092strange\u00E2\u0080\u0093 characters";
String result = UTF8Fixer.fixUTF8Characters(subject);
System.out.printf("Subject: %s%n", subject);
System.out.printf("Result: %s%n", result);
}
}
输出:
Subject: String with “strange” characters
Result: String with ‒strange– characters
答案 1 :(得分:2)
答案 2 :(得分:2)
您的文件似乎是UTF-8编码的,但您正在阅读它,就好像它是像Windows-1252这样的单字节编码。 UTF-8使用三个字节来编码每个字符,但是当您将其解码为windows-1252时,每个字节都被视为一个单独的字符。
使用文本时,如果可能,应始终指定编码;不要让系统使用其默认编码。在Java中,这意味着使用InputStreamReader和OutputStreamWriter而不是FileReader和FileWriter。任何相当不错的文本编辑器都应该让你指定一个编码。
至于你的实际问题,不,Java没有动态替换的内置工具(与大多数其他正则表达式不同)。但是编写自己的,甚至更好的,使用其他人写的东西并不太难。我在this answer发布了一张来自Elliott Hughes的文章。
最后一件事:在您的示例代码中,您使用replaceAll()
来执行替换,这是一种过度杀伤和可能的错误来源。由于您要匹配文字文本而不是正则表达式,因此您应该使用replace(CharSequence,CharSequence)
。这样你就不必担心意外地包括一个正则表达式元字符并且变得邋。。
答案 3 :(得分:-1)
不要对HTML使用正则表达式。使用真正的解析器。
这也可以帮助您解决可能遇到的任何角色编码。