2010-06-10 2 views
14

J'ai quelques fichiers texte volumineux qui vont effectuer une correspondance consécutive sur (juste capturer, pas remplacer). Im pensant que ce n'est pas une bonne idée de garder le fichier entier en mémoire, mais plutôt utiliser un Reader.Exécution d'une regex sur un flux

Ce que je sais de l'entrée est que s'il y a une correspondance, elle ne va pas dépasser plus de 5 lignes. Donc, mon idée était d'avoir une sorte de tampon qui garde juste ces 5 lignes, ou alors, faites la première recherche, et continuez. Mais il doit "savoir" où le match regex s'est terminé pour que cela fonctionne. Par exemple, si la correspondance se termine à la ligne 2, la recherche suivante doit commencer ici. Est-il possible de faire quelque chose comme ça dans un efficace façon?

Répondre

26

Vous pouvez utiliser un Scanner et la méthode findWithinHorizon:

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

De l'api sur findWithinHorizon:

Si l'horizon est 0, l'horizon est ignoré et cette méthode continue à rechercher par l'entrée recherchant le motif spécifié sans limite. Dans ce cas, il peut mettre en mémoire tampon toutes les entrées qui recherchent le motif.

Une remarque: Lorsque correspondance sur plusieurs lignes, vous pouvez regarder les constantes Pattern.MULTILINE et Pattern.DOTALL.

+0

+1; et lisez l'API pour comprendre comment 'Scanner' gère' IOException'. – polygenelubricants

2

Streamflyer est capable d'appliquer des expressions régulières sur les flux de caractères.

Notez que je suis l'auteur de celui-ci.

-5

Avec Java8 vous pouvez le faire assez simplement et peut-être dans parallèle-

// 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())); 

Une autre façon peut être -

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

vous avez pris ce contenu d'une autre réponse sans le référencer (http://stackoverflow.com/a/24663422/1902625) et il n'a même pas été fait complètement. La méthode 'matcherStream' n'est pas définie. – 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

Pouvez-vous s'il vous plaît améliorer votre message prometteur en ajoutant un exemple d'utilisation du code et un exemple de sortie? – Stephan

2

L'implémentation Java du moteur d'expression régulière semble impropre à la diffusion en continu En traitement. Je préférerais préconiser une autre approche fondée sur les «combinateurs de dérivées».

Le chercheur Matt aurait-a publié les messages pertinents sur "combinateurs dérivés" sur son blog et propose une implémentation Scala ici:

De mon côté, je réussissais pour améliorer cette implémentation en ajoutant une certaine capacité de "capture", mais je pense que cela pourrait avoir un impact significatif sur la consommation de mémoire.