0

Javaのスキャナーライブラリを使用して大きなファイルのセクションを解析しようとしていますが、このテキストを解析するための最適なルートを決定するのに苦労しています。

SECTOR 199
FLAGS 0x1000
AMBIENT LIGHT 0.67
EXTRA LIGHT 0.00
COLORMAP 0
TINT 0.00 0.00 0.00
BOUNDBOX 7.399998 8.200002 6.199998 9.399998 8.500000 7.099998
COLLIDEBOX 7.605121 8.230770 6.200000 9.399994 8.469233 7.007693
CENTER 8.399998 8.350001 6.649998
RADIUS 1.106797
VERTICES 12
0: 1810
1: 1976
2: 1977
3: 1812
4: 1978
5: 1979
6: 1820
7: 1980
8: 1821
9: 1981
10: 1982
11: 1811
SURFACES 1893 8

オプションのフィールド(SOUND、COLLIDEBOX)がいくつかあるため、ファイルの前の部分で行っていたように、特定の順序で解析することはできません。ひどく非効率にすることなくこれを行う方法がわかりません。現時点では、各行を解析し、S​​tring.split( "\ s +")で分割して値を取得することを考えていますが、私は私が持っているかもしれない他のオプションに興味があります。:\

4

4 に答える 4

2

入力は、本格的なパーサーを保証するのに十分なほど複雑に見えます。ANTLR ( http://www.antlr.org/ )などのライブラリを使用することをお勧めします。

于 2010-08-17T13:11:55.720 に答える
1

最初に、次のようなキーワードで列挙型を定義します。

 public enum Keyword {SECTOR, FLAGS, AMBIENT, EXTRA, COLORMAP, TINT, 
    BOUNDBOX, COLLIDEBOX, CENTER, RADIUS, VERTICES, SURFACES}

解析は行ごとに実行でき、空白文字で分割できます。次に、最初の要素を Keyword クラスの列挙型に変換し、単純な switch コンストラクトを使用して値を処理します。

public Model parse(List<String> lines) {

   Model model = new Model();

   Iterator<String> it = lines.iterator();
   while(it.hasNext()) {
      String[] elements = it.next().split("\s+");

      switch(Keyword.valueOf(elements[0])) {
        case SECTOR: model.addSector(elements[1]); break;
        case FLAGS: model.addFlags(elements[1]); break;
        // ...
        case VERTICES:
          int numberOfVertices = Integer.parseInt(elements[1]);
          for (int i = 0; i < numberOfVertices; i++) {
             elements = it.next().split("\s+");
             model.addVertice(i, elements[1]);
          }
          break;
        case default:
          // handle malformed line

      }
   }
   return model;
}
于 2010-08-17T14:04:04.227 に答える
1

このアプローチはどうですか:

find next command (SECTOR, FLAGS, AMBIENT LIGHT, EXTRA LIGHT, etc)
no command found? -> output error and stop
map to command implementation 
execute command (pass it the scanner and your state holder)
command impl handles specific reading of arguments
rinse, repeat,...

コマンド インターフェイスを作成する必要があります。

public interface Command {
    String getName();
    void execute(Scanner in, ReadState state);
}

遭遇する可能性のあるコマンドの種類ごとに、それを個別に実装します。

public class SectorCommand implements Command {
    public String getName() {
        return "SECTOR";
    }
    public void execute(Scanner in, ReadState state) {
        state.setSector(in.nextInt());
    }
}

コマンドを見つけるためのある種のファクトリ:

public class CommandFactory {

    private Map<String, Command> commands;
    public CommandFactory() {
        commands = new HashMap<String, Command>();
        addCommand(new SectorCommand());
        // add other commands
    }
    public Command findCommand(Scanner in) {
        for (Map.Entry<String, Command> entry : commands.entrySet()) {
            if (in.findInLine(entry.getKey())) {
                return commands.get(entry.getValue);
            }
        }
        throw new IllegalArgumentException("No command found");
    }
    private void addCommand(Command command) {
        commands.put(command.getName(), command); 
    }
}

(このコードはコンパイルできない可能性があります)

于 2010-08-17T14:27:06.240 に答える
0

ファイルが非常に大きい場合は、java.io.RandomAccessFile を使用することをお勧めします。解析する領域をスキップでき、非常に高速です。ファイル全体をメモリにマップすると、アプリケーションの速度が低下する可能性があります。

java.util.StringTokenizer を使用して単純な大文字と小文字を分割することもできます。たとえば、空白、コンマなどです。正規表現よりも高速です。

于 2010-08-17T14:29:50.670 に答える