私はまだJava言語とライブラリに慣れていません...私はPythonでこの種のパターンをよく使用しますが、これをJavaでどのように実装すべきか疑問に思います。
ある種のxmlマーキングを使用して、巨大なファイルを1行ずつ読み取る必要があります(入力を生成しているので、あいまいさはないと確信しています)
以下のPythonコードのように、巨大なファイルのいくつかの部分を繰り返し処理したいと思います。
(yield /pythonイテレータパターンを使用しています...Javaに同等のものはありますか?私は本当に好きですfor item in my collection: yield something_about(many items)
)
この種の動作を実装するための最良の(java)方法は何でしょうか?
どうも
最初の編集:ところで、ファイルと[python list]を使用するときに、Pythonの観点から利用できるListとFileの間の同様のマッピングにも興味があります。もちろん、Javaで可能であれば=>回答:JeffFosterを参照してください。使用の提案: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
出力:
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>']
----------
以下のJeffFosterの答えに直接触発されたので、これが私の問題を解決し、私の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());
}
});
}
}
2番目の編集: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; }
}