2010-06-10 19 views
14

Tengo algunos archivos de texto grandes que voy a preformar coincidencias consecutivas (solo capturando, no reemplazando). Estoy pensando que no es una buena idea mantener todo el archivo en la memoria, sino usar un Reader.Realización de expresiones regulares en una secuencia

Lo que sé sobre la entrada es que si hay una coincidencia, no va a abarcar más de 5 líneas. Entonces mi idea era tener algún tipo de buffer que mantenga estas 5 líneas, o sea, hacer la primera búsqueda y continuar. Pero tiene que "saber" dónde terminó el partido de expresiones regulares para que esto funcione. Por ejemplo, si el partido termina en la línea 2, debería comenzar la próxima búsqueda desde aquí. ¿Es posible hacer algo como esto de una manera eficiente?

Respuesta

26

Se puede usar un Scanner y la findWithinHorizon método:

Scanner s = new Scanner(new File("thefile")); 
String nextMatch = s.findWithinHorizon(yourPattern, 0); 

de la API de findWithinHorizon:

Si horizonte es 0, entonces el horizonte se ignora y este método sigue buscando a través la entrada buscando el patrón especificado sin límite. En este caso, puede almacenar toda la búsqueda de entrada para el patrón.

Una nota al margen: Cuando se coincida en varias líneas, es posible que desee ver en las constantes Pattern.MULTILINE y Pattern.DOTALL.

+0

+1; y lea la API para entender cómo 'Scanner' maneja' IOException'. – polygenelubricants

2

Streamflyer es capaz de aplicar expresiones regulares en secuencias de caracteres.

Tenga en cuenta que soy el autor de la misma.

-5

Con Java8 puede hacerlo bastante simple y posiblemente en paralelo ha

// Create a pattern-matcher 
private static final Pattern emailRegex = Pattern.compile("([^,]+?)@([^,]+)"); 

//Read content of a file 
String fileContent = Files.lines(Path.get("/home/testFile.txt") 
           .collect(Collector.join(" ")); 
// Apply the pattern-matcher 
List<String> results = matcherStream(emailRegex.matcher(fileContent)) 
          .map(b -> b[2]) 
          .collect(Collector.toList())); 

Otra forma puede ser -

List<String> results = Files.lines(Path.get("/home/testFile.txt") 
           .parallelStream() 
           .forEach(s -> "use regex") 
           .collect(Collector.toList()); 
+0

tomó este contenido de otra respuesta sin hacer referencia a él (http://stackoverflow.com/a/24663422/1902625) y ni siquiera se realizó por completo. El método 'matcherStream' no está definido. – haventchecked

0
import java.io.*; //BufferedReader //FileReader //FileWriter //PrintWriter 
import java.io.IOException; 
import java.util.Scanner; 
import java.util.regex.*; 

public class ScannerReader { 

    public static void main(String[] args) { 

     try { 
      ReadDataFromFileTestRegex("[A-Za-z_0-9-%$!][email protected][A-Za-z_0-9-%!$]+\\.[A-Za-z]{2,4}", 
             "C:\\Users\\Admin\\Desktop\\TextFiles\\Emails.txt", 
             "C:\\Users\\Admin\\Desktop\\TextFiles\\\\output.txt"); 
     } catch (Exception e) { 
      System.out.println("File is not found"); 
      e.printStackTrace(); 
     }  
    } 

    public static void ReadDataFromFileTestRegex (String theReg, String FileToRead, String FileToWrite) throws Exception { 

     PrintWriter Pout = new PrintWriter(FileToWrite);    
     Pattern p = Pattern.compile(theReg); 
     BufferedReader br = new BufferedReader (new FileReader(FileToRead)); 
     String line = br.readLine();  
     while (line != null) {   
      Matcher m = p.matcher(line); 
      while (m.find()) { 
       if (m.group().length() != 0) { 
        System.out.println(m.group().trim()); 
       }    
       System.out.println("Start index: " + m.start()); 
       System.out.println("End index : " + m.end()); 
       Pout.println(m.group()); //print the result to the output file 
      } 
      line = br.readLine(); 
     } 
     Pout.flush(); 
     br.close(); 
     Pout.close(); 
    } 
} 
+0

¿Puede mejorar su publicación prometedora agregando un uso de código de muestra y un resultado de muestra? – Stephan

2

La aplicación java de motor de expresiones regulares parece inadecuado para el streaming tratamiento.

Preferiría abogar por otro enfoque enraizado en "derivadores combinados".

El investigador Matt Podría ha publicado mensajes relevantes sobre "combinadores derivados" en su blog y sugiere una aplicación Scala aquí:

Por mi parte, tengo éxito para mejorar esta implementación agregando alguna capacidad de "captura", pero creo que podría tener un impacto significativo en el consumo de memoria.

Cuestiones relacionadas