一个正则表达式来统治它们(有效)?

时间:2010-09-02 03:48:57

标签: java html regex string

嘿伙计们,我一直在尝试解析HTML文件以从中抓取文本,而且每隔一段时间,我就会得到一些非常奇怪的字符,如à€œ。我确定它是“智能引号”或卷曲的标点符号导致我的所有问题,所以我的临时修复是单独搜索并用相应的HTML代码替换所有这些字符。我的问题是,是否有这样一种方法可以使用一个正则表达式(或其他东西)只搜索一次字符串,并根据其中的内容替换它需要的内容?我现在的解决方案如下:

line = line.replaceAll( "“", "“" ).replaceAll( "”", "”" );
line = line.replaceAll( "–", "–" ).replaceAll( "—", "—" );
line = line.replaceAll( "‘", "‘" ).replaceAll( "’", "’" ); 

由于某种原因,似乎可能有更好的,可能更有效的方法来做到这一点。任何意见都非常感谢。

谢谢,
-Brett

4 个答案:

答案 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 &#8210;strange&#8211; characters

答案 1 :(得分:2)

here上有一个巨大的线程,它向您展示了使用正则表达式解析HTML的原因。

寻找外部库来完成此任务。一个例子是:JSoup。他们的网页上还有一个可以使用的教程。

答案 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使用正则表达式。使用真正的解析器。

这也可以帮助您解决可能遇到的任何角色编码。