Использование нескольких регулярных выражений для сканирования файла - PullRequest
3 голосов
/ 19 апреля 2011

У меня есть некоторый код, который принимает URL, читает файл и ищет строки, соответствующие заданному регулярному выражению, и добавляет любые совпадения в arrayList до тех пор, пока он не достигнет конца файла. Как я могу изменить свой код так, чтобы при чтении файла я мог проверять наличие других строк, соответствующих другим регулярным выражениям на одном проходе, вместо того, чтобы проверять файл несколько раз, проверяя каждое другое регулярное выражение?

    //Pattern currently being checked for
    Pattern name = Pattern.compile("<a id=.dg__ct(.+?)_hpl1.>(.+?)</a>");

    //Pattern I want to check for as well, currently not implemented
    Pattern date = Pattern.compile("[0-9]{2}/[0-9]{2}/[0-9]{4}");

    Matcher m;
    InputStream inputStream = null;
    arrayList = new ArrayList<String>();
    try {
        URL url = new URL(
                "URL to be read");
        inputStream = (InputStream) url.getContent();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        InputStreamReader isr = new InputStreamReader(inputStream);
        BufferedReader buf = new BufferedReader(isr);
        String str = null;
        String s = null;

        try {
            while ((str = buf.readLine()) != null) {

                m = name.matcher(str);
                while(m.find()){
                    s = m.group();
                    arrayList.add(s);
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Ответы [ 4 ]

6 голосов
/ 19 апреля 2011

Начиная с 2 Matchers, вы должны использовать список.И вам не следует делать это в блоке finally, который вводится в случае сбоя одного из потоков.Вместо этого блок finally должен использоваться для закрытия ресурсов.

    List <Pattern> patterns = new ArrayList <Pattern> ();
    //Pattern currently being checked for
    patterns.add (Pattern.compile ("<a id=.dg__ct(.+?)_hpl1.>(.+?)</a>"));
    //Pattern I want to check for as well, currently not implemented
    patterns.add (Pattern.compile ("[0-9]{2}/[0-9]{2}/[0-9]{4}"));
    BufferedReader buf = null;
    List <String> matches = new ArrayList <String> ();
    try {
        URL url = new URL ("URL to be read");
        InputStream inputStream = (InputStream) url.getContent ();
        InputStreamReader isr = new InputStreamReader (inputStream);
        buf = new BufferedReader (isr);
        String str = null;
        while ((str = buf.readLine ()) != null) 
        {
            for (Pattern p : patterns) 
            {
                Matcher m = p.matcher (str);
                while (m.find ()) 
                    matches.add (m.group ());
            }
        }       
    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }
    finally  
    {
        if (buf != null) 
            try { buf.close (); } catch (IOException ignored) { /*empty*/}
    }

Не исправлено в коде: вместо «Исключение» вы должны перечислить конкретные исключения.А Matcher просто используется внутри самого внутреннего цикла, поэтому объявляйте его там, а не в большем объеме.Небольшой объем позволяет легко рассуждать об использовании переменной.

Я не уверен, можно ли использовать util.Scanner.class, чтобы сделать чтение из URL-адреса более простым.Посмотрите документацию.

2 голосов
/ 19 апреля 2011

Вместо регулярного выражения используйте библиотеку Java, которая понимает, как правильно анализировать HTML.

Например, проверьте ответы на следующие вопросы: Разбор Java HTML

1 голос
/ 19 апреля 2011
  1. Создание двух Matcher объектов

    //Pattern currently being checked for
    Matcher nameMatcher = Pattern.compile("<a id=.dg__ct(.+?)_hpl1.>(.+?)</a>").matcher();
    
    //Pattern I want to check for as well, currently not implemented
    Matcher dateMatcher = Pattern.compile("[0-9]{2}/[0-9]{2}/[0-9]{4}").matcher();
    
    
    // other stuff...
    
  2. Проверка строки чтения по каждому сопоставителю

    while ((str = buf.readLine()) != null) {
    
            nameMatcher.reset(str);
    
            while(nameMatcher.find()){
                s = nameMatcher.group();
                arrayList.add(s);
            }
    
            dateMatcher.reset(str);
    
            while(nameMatcher.find()){
                s = nameMatcher.group();
                arrayList.add(s);
            }
        }
    

Важно

Используйте reset(Charsequence) вместо выделения нового объекта Matcher каждый раз.

1 голос
/ 19 апреля 2011

Просто получите новый сопоставитель для другого шаблона

   Matcher m2 = date.matcher(str);
   ... // do whatever you want to do with this pattern match

Кстати, вообще не очень хорошая идея - анализировать HTML с помощью регулярных выражений. ( ссылка об., Помощник Не анализирует HTML с сотрудником Regex , ответственным )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...