1

私はまだ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; }
}
4

2 に答える 2

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); 
    }
};
于 2012-06-20T13:31:46.973 に答える
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);
// ...

お役に立てれば ...

于 2012-06-20T13:50:16.480 に答える