用Java Scanner库解析这个最有效的方法是什么?
我试图用Java的Scanner库解析一个大文件的一部分,但是我很难确定解析这个文本的最佳路径用Java Scanner库解析这个最有效的方法是什么?,java,performance,java.util.scanner,Java,Performance,Java.util.scanner,我试图用Java的Scanner库解析一个大文件的一部分,但是我很难确定解析这个文本的最佳路径 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
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、collizebox),因此我无法像处理文件的前一部分那样按特定顺序进行解析。我不确定如何在不让它变得非常低效的情况下进行此操作,目前我一直在考虑解析每一行,然后用字符串将其拆分。拆分(“\s+”)以获取值,但我很好奇我还有什么其他选项:\ 输入看起来非常复杂,足以支持一个完整的解析器。我建议使用一个库,比如ANTLR()。输入看起来很复杂,足以支持一个完整的解析器。我建议使用ANTLR()之类的库。我首先用关键字定义一个枚举,如:
public enum Keyword {SECTOR, FLAGS, AMBIENT, EXTRA, COLORMAP, TINT,
BOUNDBOX, COLLIDEBOX, CENTER, RADIUS, VERTICES, SURFACES}
解析可以逐行进行,以空格字符进行拆分。然后,我将第一个元素从关键字类转换为枚举,并使用一个简单的开关构造来处理值:
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;
}
公共模型解析(列表行){
模型=新模型();
迭代器it=lines.Iterator();
while(it.hasNext()){
String[]elements=it.next().split(“\s+”);
开关(关键字.valueOf(元素[0])){
案例扇区:model.addSector(元素[1]);break;
案例标志:model.addFlags(元素[1]);break;
// ...
案例顶点:
int numberoftexts=Integer.parseInt(元素[1]);
对于(int i=0;i
我首先用关键字定义一个枚举,如:
public enum Keyword {SECTOR, FLAGS, AMBIENT, EXTRA, COLORMAP, TINT,
BOUNDBOX, COLLIDEBOX, CENTER, RADIUS, VERTICES, SURFACES}
解析可以逐行进行,以空格字符进行拆分。然后,我将第一个元素从关键字类转换为枚举,并使用一个简单的开关构造来处理值:
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;
}
公共模型解析(列表行){
模型=新模型();
迭代器it=lines.Iterator();
while(it.hasNext()){
String[]elements=it.next().split(“\s+”);
开关(关键字.valueOf(元素[0])){
案例扇区:model.addSector(元素[1]);break;
案例标志:model.addFlags(元素[1]);break;
// ...
案例顶点:
int numberoftexts=Integer.parseInt(元素[1]);
对于(int i=0;i
这种方法怎么样:
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);
}
}
公共类CommandFactory{
专用地图命令;
公共命令工厂(){
commands=newhashmap();
addCommand(新的SectorCommand());
//添加其他命令
}
公共命令findCommand(扫描仪输入){
for(Map.Entry:commands.entrySet()){
if(在.findInLine(entry.getKey())中){
返回命令.get(entry.getValue);
}
}
抛出新的IllegalArgumentException(“未找到命令”);
}
私有void addCommand(Command命令){
commands.put(command.getName(),command);
}
}
(此代码可能无法编译)此方法如何:
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);
}
}
公共类CommandFactory{
专用地图命令;
公共命令工厂(){
commands=newhashmap();
addCommand(新的SectorCommand());
//添加其他命令
}
公共命令findCommand(扫描仪输入){
for(Map.Entry:commands.entrySet()){
if(在.findInLine(entry.getKey())中){
返回命令.get(entry.getValue);
}
}
抛出新的IllegalArgumentException(“未找到命令”);
}
私有void addCommand(Command命令){
commands.put(command.getName(),command);
}
}
(此代码可能无法编译)如果文件很大,我建议您可以使用java.io.RandomAccessFile,它可以跳过您想要解析的任何区域,而且速度非常快。若将整个文件映射到memnory,可能会降低应用程序的速度
也可以使用java.util.StringTokenizer拆分简单的大小写。例如,空格、逗号等。它比正则表达式快。如果文件很大,我建议您可以使用java.io.RandomAccessFile,它可以跳过您想要解析的任何区域,而且速度非常快。若将整个文件映射到memnory,可能会降低应用程序的速度
也可以使用java.util.StringTokenizer拆分简单的大小写。例如,空格、逗号等。它比正则表达式快。可能必须采用这种方法,尽管我不知道是否需要“重写”我的代码:已经在这方面投入了很多时间,但是谢谢你的建议3我可能不得不走这条路,但我不知道是否要“重写”我的代码:已经在这方面投入了很多时间,但是谢谢你的建议3我喜欢这件的外观。干净、简单,并且已经检查了格式错误的文件。我现在可以用它来测试。我喜欢它的外观。干净、简单,并且已经检查了格式错误的文件。我现在可以使用它,用于测试目的。