2012-06-20 61 views
1

我對Java語言和庫還是一個新手......我經常在Python中使用這種模式,並想知道我應該如何使用Java來實現這一模式。在Java中實現這種模式的最佳方式(裏面的Python示例)?

我需要逐行讀取一個巨大的文件行,用某種形式的XML標記(我生產的投入,所以我肯定不會有任何歧義)

我想裏面的一些迭代像下面的Python代碼的巨大文件的部分:

(使用收益率/ Python的迭代器模式...有沒有在Java中任何equivallent我真的很喜歡for item in my collection: yield something_about(many items)?)

這將是最好的( java)的方式來實現這種行爲?

THX

第一編輯: BTW,我本來也有興趣列表和文件之間的相似映射使用文件和文件時可用從一個Python的點[Python列表,如果中當然,也可以使用Java =>回答:看到使用的傑夫 - 福斯特建議:Apache.IOUtils

def myAcc(instream, start, end): 
    acc = [] 
    inside = False 
    for line in instream: 
     line = line.rstrip() 
     if line.startswith(start): 
      inside = True 
     if inside: 
      acc.append(line) 
     if line.startswith(end): 
      if acc: 
       yield acc 
       acc = [] 
      inside = False 


f = open("c:/test.acc.txt") 

s = """<c> 
<a> 
this is a test 
</a> 
<b language="en" /> 
</c> 
<c> 
<a> 
ceci est un test 
</a> 
<b language="fr" /> 
</c> 
<c> 
<a> 
esta es una prueba 
</a> 
<b language="es" /> 
</c>""" 

f = s.split("\n") # here mimic for a input file... 

print "Reading block from <c> tag!" 
for buf in myAcc(f, "<c>", "</c>"): 
    print buf # actually process this inner part... printing is for simplification 
    print "-" * 10 

print "Reading block from <a> tag!" 
for buf in myAcc(f, "<a>", "</a>"): 
    print buf # actually process this inner part... 
    print "-" * 10  

OUTPUT:

Reading block from <c> tag! 
['<c>', '<a>', 'this is a test', '</a>', '<b language="en" />', '</c>'] 
---------- 
['<c>', '<a>', 'ceci est un test', '</a>', '<b language="fr" />', '</c>'] 
---------- 
['<c>', '<a>', 'esta es una prueba', '</a>', '<b language="es" />', '</c>'] 
---------- 
Reading block from <a> tag! 
['<a>', 'this is a test', '</a>'] 
---------- 
['<a>', 'ceci est un test', '</a>'] 
---------- 
['<a>', 'esta es una prueba', '</a>'] 
---------- 

所以直接通過下面的傑夫 - 福斯特的回答啓發,這裏是一個試圖解決我的煩惱,做這樣的事情比我的Python代碼:

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.UnsupportedEncodingException; 
import java.util.ArrayList; 
import java.util.List; 

interface WorkerThing { 
    public void doSomething(List<String> acc); 
} 

class ThatReadsLargeFiles { 
    public void readAHugeFile(BufferedReader input, String start, String end, WorkerThing action) throws IOException { 
     // TODO write some code to read through the file and store it in line 
     List<String> acc = new ArrayList<String>(); 
     String line; 
     Boolean inside = false; 
     while ((line = input.readLine()) != null) { 
      if (line.equals(start)) { 
       inside = true; 
      } 
      if (inside) { 
       acc.add(line); 
      } 
      if (line.equals(end)) { 
       if (acc != null && !acc.isEmpty()) { // well not sure if both are needed here... 
        // Here you are yielding control to something else 
        action.doSomething(acc); 
        //acc.clear(); // not sure how to empty/clear a list... maybe : List<String> acc = new ArrayList<String>(); is enough/faster? 
        acc = new ArrayList<String>(); // looks like this is the *right* way to go! 
       } 
       inside = false; 
       // ending 
      } 
     } 
     input.close(); 
    } 
} 

public class YieldLikeTest { 

    public static void main(String[] args) throws IOException { 


     String path = "c:/test.acc.txt"; 

     File myFile = new File(path); 
     BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(myFile), "UTF8")); 
     //BufferedReader in = new BufferedReader(new FileReader(path, "utf8")); 

     new ThatReadsLargeFiles().readAHugeFile(in, "<a>", "</a>", new WorkerThing() { 
       public void doSomething(List<String> acc) { 
        System.out.println(acc.toString()); 
       } 
     }); 


    } 

} 

第二編輯:我太快接受這個答案,其實,我還是很懷念,並有一個誤區:我不知道如何獲得並保持acc內容的痕跡在@最上層(不是匿名內部類)。因此,它可以調用用於別的東西比打印比方說實例化一個類,並做其他處理...產量允許這種用法,我不明白我怎麼能適應所提出的答案有這樣的行爲。對不起,我的Python使用/示例很簡單。

所以這裏是從傑夫 - 福斯特解釋得出,用於存儲ACC答案:

class betweenWorker implements WorkerThing { 

    private List<String> acc; 

    public void process(List<String> acc) { 
     this.acc = acc; 
    } 
    public List<String> getAcc() { return this.acc; } 
} 
+0

我r讀縮小你以前無效的代碼。我希望我說得對。 (這就是爲什麼你應該使用空格,而不是縮進標籤,最重要的是,不要混合這兩個) –

+0

謝謝!是的,當我在另一個文本編輯器中粘貼時,我錯過了這一點,只是爲了在此處插入空格來粘貼代碼,所以代碼可以看作是這樣。 – user1340802

回答

1

Java不支持類似的yield,但你可以通過創建一個接口實現同樣的事情這封裝了您將在各行上執行的操作。

interface WorkerThing { 
    void doSomething(string lineOfText); 
} 

class ThatReadsLargeFiles { 
    public void readAHugeFile(WorkerThing actions) { 
     // TODO write some code to read through the file and store it in line 

     // Here you are yielding control to something else 
     action.doSomething(line); 
    } 
} 

當你使用它,你可以使用匿名接口實現,使事情稍微更愜意。

new ThatReadsLargeFiles().readAHugeFile(new WorkerThing() { 
    void doSomething(string text) { 
     System.out.println(text); 
    } 
}; 
+0

謝謝你,編輯我的問題來複制你的答案,幫助我建立一個工作代碼。 BTW是否可以映射文件和列表?所以它可以像Python一樣通用? – user1340802

+0

Apache.IOUtils可以提供幫助器方法來將文件轉換爲列表,但是沒有通用的(即內置於語言中)方式來執行此操作。 –

+0

謝謝!順便說一句,我實際上有這個解決方案的另一個麻煩,這是從我的理解,我怎麼可以分配在'doSomething'裏面的'acc'到一個上層var?這樣它可以在上層調用中使用?或者可能是我應該問另一個SO問題?最好的問候 – user1340802

1

如果我理解正確的Python代碼,你的任務,這可以通過以下方式來完成:

// callback representing function to be invoked on String array 
public interface Callback { 
    void process(List<String> lines); 
} 

public void processFile(final String path, final String start, final String end, final Callback callback) { 
    BufferedReader reader = null; 
    try { 
     final FileReader fileReader = new FileReader(path); 
     reader = new BufferedReader(fileReader); 

     List<String> lines = new ArrayList<String>(); 
     boolean inside = false; 

     String line = null; 
     while((line = reader.readLine()) != null) { 
      if(line.startsWith(start)) { 
       inside = true; 
      } 

      if(inside) { 
       lines.add(line); 
      } 

      if(line.startsWith(end)) { 
       inside = false; 
       callback.process(lines); 
       lines = new ArrayList<String>(); 
      } 
     } 
    // following is just boilerplate to correctly close readers 
    } catch(final IOException ex) { 
     ex.printStackTrace(); 
    } finally { 
     if(reader != null) { 
      try { 
       reader.close(); 
      } catch(final IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

然後在你的代碼的某個地方,你可以調用這個方法就像這裏:

// ... 
// creating instance of class implementing Callback interface (this is called 'anonymous' class in Java) 
final Callback myCallback = new Callback() { 
    public void process(List<String> lines) { 
     for(String line : lines) { 
      System.out.println(line); 
     } 
    } 
}; 
processFile("path/to/file", "<c>", "</c>", myCallback); 
processFile("path/to/file", "<a>", "</a>", myCallback); 
// ... 

希望這有助於...

+0

非常感謝你Yura,對不起,我已經接受了Jeff Foster的回答,因爲他是第一個,但你比我快重寫te正確的一段代碼!所以投票也爲你的。 – user1340802

+0

當然,沒問題 - 謝謝:) – Yura

相關問題