2016-01-28 10 views
5
public final Pattern PATTERN = Pattern.compile("<abc:c\\sabc:name=\"(\\S+)\"\\sabc:type=\"(\\S+)\">"); 
    try (Stream<String> stream = Files.lines(template.getPath())) { 
     stream.filter(s -> PATTERN.matcher(s).find()).forEach(System.out::println); 

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

पैटर्न पैटर्न ठीक काम करता है लेकिन मैं अपने समूह को कैसे पकड़ सकता/सकती हूं? फिलहाल मुझे केवल स्ट्रिंग मिलती है।फ़ाइल स्ट्रीम

+2

क्या यह पैटर्न लाइन में 1 से अधिक बार प्रदर्शित हो सकता है? – Tunaki

+0

मैं exatcly नहीं जानता लेकिन मैं बात - हाँ;) – Tobias

+2

'.filter (एस -> PATTERN.matcher (s) .find())' .filter (PATTERN.asPredicate()) के बराबर है ... – Holger

उत्तर

7

पैटर्न आप आवेदन कर रहे हैं केवल एक लाइन के लिए एक बार दिखाई देता है, तो आप अपने एक Stream<Matcher> में Stream<String>, लाइनों है कि नमूने का मिलान को फ़िल्टर और अंत में उन्हें एक सरणी में भंडारण के द्वारा समूह 1 और 2 को निकालने मैप कर सकते हैं।

try (Stream<String> stream = Files.lines(Paths.get(""))) { 
    stream.map(PATTERN::matcher) 
      .filter(Matcher::find) 
      .map(m -> new String[] { m.group(1), m.group(2) }) 
      .forEach(a -> System.out.println(Arrays.toString(a))); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

पैटर्न एक से अधिक समय दिखाई देता है, तो हम Matcher से अधिक पाश करने की आवश्यकता होगी find() जब तक रिटर्न false। इस मामले में, हम

try (Stream<String> stream = Files.lines(Paths.get(""))) { 
    stream.map(PATTERN::matcher) 
      .flatMap(m -> { 
       List<String[]> list = new ArrayList<>(); 
       while (m.find()) { 
        list.add(new String[] { m.group(1), m.group(2) }); 
       } 
       return list.stream(); 
      }) 
      .forEach(a -> System.out.println(Arrays.toString(a))); 

जावा 9 में, वहाँ एक नई विधि Matcher.results() परिणामों की एक Stream<MatchResult> को पुनः प्राप्त करने में हो सकता है हो सकता था। हम इसे 2 अलग find और group संचालन के बजाय यहां उपयोग कर सकते हैं।

+5

इसके अलावा (केवल जावा 9) देखें ['Scanner.findAll()'] (http://download.java.net/jdk9/docs/api/java/util/Scanner.html#findAll-java.util.regex.Pattern -) 'स्ट्रीम 'प्राप्त करने के लिए। एक स्कैनर लाइन-आधारित पढ़ने और इसकी सीमाओं से परहेज करते हुए सीधे फ़ाइल को पढ़ सकता है। –

+1

@StuartMarks बहुत सुविधाजनक जोड़! मुझे यह नहीं पता था, इसे लाने के लिए धन्यवाद। – Tunaki

+1

नेस्टेड 'forEach' बदसूरत लग रहा है। इसके बजाय पिछले चरण के लिए 'flatMap' का उपयोग करें। फिर आप 'List' को 'Stream.builder' से बदल सकते हैं जो संभावित रूप से अधिक कुशल है। – Holger

संबंधित मुद्दे