Regex для поиска и замены текста в большом файле

Я ищу многострочный шаблон в огромном файле, и если он найден, нужно заменить содержимое. Я хочу сделать это эффективным способом с точки зрения памяти. Моя текущая реализация читает текст из файла кусками по 4096 байт. Затем он применяет замену поиска по регулярному выражению и сохраняет результат в выходном потоке буфера. Это дает мне некоторые улучшения памяти, поскольку я не загружаю весь файл в память, однако я делаю много операций ввода-вывода с вызовами map/flush. Нужны предложения по дальнейшему улучшению моего кода. Кроме того, алгоритм дает сбой, если искомый шаблон разделен на смежные фрагменты. Любые идеи о том, как эффективно искать и заменять текст, разделенный на соседние фрагменты. Предположения: текст для поиска всегда меньше 4096 байт.

public void searchAndReplace (String inputFilePath, String outputFilePath) {

    Pattern HEADER_PATTERN =  Pattern.compile("<a [^>]*>[^(</a>)]*</a>", Pattern.DOTALL);
    Charset UTF8 = Charset.forName("UTF-8");
    File outputFile = new File(outputfilepath);
    if (!outputFile.exists()) {
        outputFile.createNewFile();
    }

    FileInputStream inputStream = new FileInputStream(new File(inputfilepath));
    FileOutputStream outputStream = new FileOutputStream(outputFile);

    FileChannel inputChannel = inputStream.getChannel();

    final long length = inputChannel.size();
    long pos = 0;
    while (pos < length) {
        int remaining = (int)(length - pos) > 4096 ? 4096 : (int)(length - pos);
        MappedByteBuffer map = inputChannel.map(FileChannel.MapMode.READ_ONLY, pos, remaining);
        CharBuffer cbuf = UTF8.newDecoder().decode(map);
        Matcher matcher = HEADER_PATTERN.matcher(cbuf);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "Some text");
        }
        matcher.appendTail(sb);
        outputStream.write(sb.toString().getBytes());
        outputStream.flush();
        pos = pos + 4096;
    }

    inputStream.close();
    outputStream.close(); 
}

person Chinmay    schedule 27.03.2015    source источник
comment
Вы должны использовать java? Если нет, то какую ОС вы используете?   -  person Bohemian♦    schedule 28.03.2015
comment
Я бы предпочел использовать java, так как я хотел бы, чтобы приложение не зависело от ОС. Хотел бы использовать ОС grep/find, если нет другой альтернативы.   -  person Chinmay    schedule 28.03.2015
comment
Почти уверен, что ваше регулярное выражение не делает то, что вы думаете: оно требует, чтобы привязка не содержала ни одного из символов (, <, /, a, > or ). Я думаю, ты действительно хочешь "<a [^>]*>.*?</a>"   -  person Bohemian♦    schedule 29.03.2015
comment
Возможно, вам следует использовать потоковый синтаксический анализатор XML, чтобы справиться с этим.   -  person Duncan Jones    schedule 02.04.2015
comment
+Дункан: Да, я сделал то же самое. Спасибо   -  person Chinmay    schedule 03.04.2015


Ответы (1)


Объявите список специальных символов, которые вряд ли будут в вашей строке. Затем проверьте свою строку, чтобы убедиться, что один из специальных символов не выходит внутри нее. Поместите специальный символ между областями, в которых вы хотите выполнить регулярное выражение. Затем вы можете выполнить поиск/замену или поиск с помощью /[^¬]*myRegExHere[^\¬]/g

person Steve Tomlin    schedule 05.05.2015