简体   繁体   English

从Java中的文本文件运行函数

[英]Run function from text file in Java

I want to implement a program that reads a text file and executes every line on it.我想实现一个读取文本文件并执行其每一行的程序。

For example if I have this txt file:例如,如果我有这个 txt 文件:

Commands.txt命令.txt
{
  t.getP().getName()
  t.getP().getAge()
  t.getP().getLocation()
}

And the following Java program:以及以下 Java 程序:

public class Test {
    private Person p;

    public Test(){
        p = new Person("Jhon", "19", "New York", "Mathematician");
    }

    public Person getP() {
        return p;
    }

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException{
        Test t = new Test();

        // Read txt file with methods
        String line1 = "t.getP().getName()";
        String line2 = "t.getP().getAge()";
        String line3 = "t.getP().getLocation()";

        // Execute methods
        Method m = t.getClass().getMethod(line1);
        m.invoke(t);

    }
}

I am getting the following error:我收到以下错误:

Exception in thread "main" java.lang.NoSuchMethodException: Test.t.getP().getName()()
    at java.lang.Class.getMethod(Class.java:1786)
    at Test.main(Test.java:24)

I understand that the program does not find any method, but I do not how to fix it.我知道该程序没有找到任何方法,但我不知道如何修复它。

Thanks in advance!提前致谢!

When you use Java Reflection to invoke methods, you need to pass the name of the function without parentheses.当您使用 Java 反射调用方法时,您需要传递不带括号的函数名称 If you have methods that require parameters, you pass those parameters to the reflection method, not the method you are invoking.如果您有需要参数的方法,则将这些参数传递给反射方法,而不是您正在调用的方法。

Assuming those methods exist in your Person class, removing the parentheses from the method names should work.假设这些方法存在于您的Person类中,从方法名称中删除括号应该有效。 Also, as @UnholySheep mentioned in the comments, you need to break down your lines in commands.txt so that each line contains the right "command" you need to invoke.此外,正如评论中提到的@UnholySheep,您需要在commands.txt中分解您的行,以便每一行都包含您需要调用的正确“命令”。 For example:例如:

Method m = Class.forName("Person").getMethod("getName");

Your parser should retrieve these parameters is some similar fashion.您的解析器应该以某种类似的方式检索这些参数。 If you pay attention to the error you are getting, you will notice two sets of parentheses at the end.如果你注意你得到的错误,你会注意到末尾有两组括号。 This is because the API is assuming the method name itself contains the characters ( and ) .这是因为 API 假定方法名称本身包含字符()

UPDATE : I don't know who downvoted this answer, so let me be clearer.更新:我不知道谁对这个答案投了反对票,所以让我更清楚一点。 You need to break down your commands.你需要分解你的命令。 You also need to obtain object p from your Test class and then invoke the methods of the Person class.您还需要从Test类中获取对象p ,然后调用Person类的方法。

Method getPerson = t.getClass().getMethod("getP");
Person p = (Person)getPerson.invoke(t);
Method getName = p.getClass().getMethod("getName");
String name = (String)getName.invoke(p);

Each of the String arguments could be in separate lines OR in the same line delimited by some character.每个String参数可以位于单独的行中,也可以位于由某个字符分隔的同一行中。 For example例如

getP|getName
getP|get
getP|getAge
getP|getLocation

You can even loop through the lines in the file, tokenize each string and pass the arguments referencing the array of method names.您甚至可以遍历文件中的行,标记每个字符串并传递引用方法名称数组的参数。

try (BufferedReader br = new BufferedReader(new FileReader(new File("Commands.txt")))) {
    String line;
    while ((line = br.readLine()) != null) {
       String tokens = line.split("|");
       Method getPerson = t.getClass().getMethod(tokens[0]);
       Person p = (Person)getPerson.invoke(t);
       Method getName = p.getClass().getMethod(tokens[1]);
       String name = (String)getName.invoke(p);
    }
}

In summary:总之:

  1. The class Test doesn't have a method called t.getP().getName() . Test类没有名为t.getP().getName()的方法。
  2. The parentheses are not part of the method name.括号不是方法名称的一部分。

UPDATE #2 : I wrote the following to demonstrate how to use reflection to do what I mentioned above AND to get the return types from the methods:更新#2 :我写了以下内容来演示如何使用反射来做我上面提到的事情并从方法中获取返回类型:

public class Person {
    private final String name;
    private final int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {return name;}
    public int getAge() {return age;}
    
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Person p = new Person("Hector", 54);
        Method getName = p.getClass().getMethod("getName");
        Method getAge = p.getClass().getMethod("getAge");
        System.out.println(getName.invoke(p));
        System.out.println(getAge.invoke(p));
        
        System.out.println("getName() returns " + getName.getReturnType().getName());
        System.out.println("getAge() returns " + getAge.getReturnType().getName());
    }
}

The above code outputs:上面的代码输出:

Hector
54
getName() returns java.lang.String
getAge() returns int

In comments, you elaborated that your goal is to do things in order to determine whether or not you want to append .toString() .在评论中,您详细说明了您的目标是做一些事情以确定您是否要附加.toString()

I have a text file with tons of lines, that comes from another program, which is a XML translator to Java kind of, but it is not perfect.我有一个包含大量行的文本文件,它来自另一个程序,它是一种将 XML 翻译成 Java 的程序,但它并不完美。 So, I want to check that all the methods calls at the end return a String.所以,我想检查最后所有的方法调用是否返回一个字符串。 I have been doing this by hand.我一直在手工做这个。 At the end the goal is, if the method does not return a String, we just append a .toString() at the end.最后的目标是,如果该方法没有返回字符串,我们只需在末尾附加一个 .toString() 。 I want to do this programmaticaly.我想以编程方式执行此操作。

With that problem statement, here's an entirely different approach:有了这个问题陈述,这是一种完全不同的方法:

  • check nothing什么都不检查
  • skip all of the reflection dynamic code evaluation from textfile stuff跳过文本文件中的所有反射动态代码评估
  • simply append .toString() everywhere只需在任何地方附加.toString()

Some of the lines will need a .toString() appended, based on what you alluded to in comments, namely that it's an "XML translator to Java kind of, but it is not perfect" .根据您在评论中提到的内容,有些行需要附加一个.toString() ,即它是一种“Java 的 XML 转换器,但它并不完美”

Some of the lines will not need it, but it is fine to tack an additional .toString() .有些行不需要它,但可以附加一个.toString() For example, this is completely valid Java:例如,这是完全有效的 Java:

"aardvark".toString().toString().toString();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM