Получение имени файла и пути .class после выполнения ProcessBuilder в java

#java #file-io #processbuilder

Вопрос:

Я создал API, который будет принимать полезную нагрузку (code, language) , которая, в свою очередь, генерирует случайное имя для сохранения файла(в зависимости от языка, на котором будут выбраны расширения) из java. полезная нагрузка из пользовательского интерфейса приведена ниже

 {"code": "class Demo{ rn"     " public static void main(String args[]){ rn"     " System.out.println("Hello Java"); rn"     " } rn"     "}", "language": "java"}  

Сохранение файлов работает должным образом , как и ожидалось, и я могу сохранить файл под C:\temp , но проблема возникает, когда я пытаюсь выполнить эти сохраненные файлы с ProcessBuilder помощью java, получая Error: Could not find or load main class BNkHZk (так как случайно сгенерированное имя файла отличается от файла класса после выполнения приведенного ниже кода).

 ProcessBuilder processBuilder = new ProcessBuilder(new String[] { "javac", fullPath }); //fullPath is C:tempBNkHZk.java Process process = processBuilder.start();  

приведенное выше выполнение создаст новый Demo.class файл. После выполнения приведенной выше команды я выполняю приведенный ниже код

 processBuilder = new ProcessBuilder(new String[] { "javac", fullPath }); Process process = processBuilder.start();  if (process.getErrorStream().read() != -1) {  System.out.println("Compilation Errors"   process.getErrorStream());  }  BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));  String line = "";   while ((line = reader.readLine()) != null) {  System.out.Println(line);  }  

Я получаю следующую ошибку Error: Could not find or load main class BNkHZk

Полная функция приведена ниже, как показано ниже

 private void ExecuteCode(String language, String code){  String tempFileName = RandomStringUtils.randomAlphanumeric(6);  // Code to creating the file and save under "C:\temp\"  String fullPath = "C:\temp\"   tempFileName  "."   language;  try {  fileWriter = new FileWriter(new File(fullPath));  fileWriter.write(code);  } catch (Exception e) {  System.out.println("IO Exception while creating new file");  e.printStackTrace();  } finally {  if (fileWriter != null) {  fileWriter.close();  }  }    ProcessBuilder processBuilder = new ProcessBuilder(new String[] { "javac", fullPath });  ////fullPath is C:tempBNkHZk.java  Process process = processBuilder.start();   if (process.getErrorStream().read() != -1) {  BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));  String line = "";   while ((line = reader.readLine()) != null) {  System.out.println(line);  }  }  //the above execution will create a new **Demo.class** file.  int exitcode = -1;  try {  exitcode = process.waitFor();  } catch (InterruptedException e) {  e.printStackTrace();  }  if (exitcode == 0) {  (  processBuilder = new ProcessBuilder(new String[] { "java","tempFileName"});//BNkHZk  Process process1 = processBuilder.start();  BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));  String line = "";   while ((line = reader.readLine()) != null) {  System.out.println(line   "n");  }  }   }  

Я получаю error Error: Could not find or load main class BNkHZk

Примечание: Поскольку я получу содержимое файла в виде строки, я не смогу сохранить имя файла так же, как .class имя. Есть ли какой-либо обходной путь, чтобы сохранить имя файла таким же, как имя .class ?? Любые предложения по обходным путям приветствуются и приветствуются. Заранее спасибо.

Ответ №1:

Есть две разные проблемы. Первый из них-это имя файла класса. Имя класса должно совпадать с именем файла. class Demo -gt; Demo.java , вот почему вы не можете использовать случайные имена файлов. Компиляция выполняется хорошо, но не запуск.

Второй — это обработка ProcessBuilder. Я предлагаю следующую схему:

 ProcessBuilder pb = new ProcessBuilder("javac.exe", "Demo.java"); pb.directory(Paths.get("path_to_java_file").toFile()); pb.redirectErrorStream(true); Process process = pb.start(); try (var infoStream = process.getInputStream()) {  infoStream.transferTo(System.out); } status = process.waitFor();  

Теперь вы можете увидеть, правильно ли выполняется компиляция.

Используйте тот же шаблон для запуска скомпилированного класса.

Комментарии:

1. Привет @Thilo Schwarz, спасибо за быстрый ответ. Поскольку я получу содержимое файла в виде строки, я не смогу сохранить имя файла таким же, как имя .class.

2. @UllasSharma Вы получаете свой исходный код в виде текста, верно? Вы должны сохранить этот код в виде файла java, Demo.java . Следующий шаг-компиляция с помощью javac, верно? Результатом компиляции является файл Demo.class . Или я неправильно понял рабочий процесс?

3. @Ullas Sharma просто создайте временный каталог, а затем ожидаемый файл Java внутри него на этапе генерации — Path fullPath = Path.of("C:/temp", tmpFileName, "Demo." language); и тогда все вышесказанное будет работать внутри временного каталога

4. @ Thilo Schwarz, я получаю содержимое только в виде текста, но я не получу точное имя класса файла, так как это динамическое содержимое. например, если вы видите JSON req ,я буду получать из пользовательского {"code": "class Sample{ public static void main(String args[]){ System.out.println("Hello Java"); }", "language": "java"} интерфейса, как должно быть в соответствии с вашим пониманием имени Sample.java файла, но я не могу получить само имя класса, так как это довольно сложно сделать из динамического текстового содержимого.

5. @DuncG я ищу обходной путь с помощью processbuilder, чтобы получить вновь созданное .class имя, содержимое только в виде текста, но я не получу точное имя класса файла, так как это динамическое содержимое. например, если вы видите JSON req ,я буду получать из пользовательского {"code": "class Sample{ public static void main(String args[]){ System.out.println("Hello Java"); }", "language": "java"} интерфейса, как должно быть в соответствии с вашим пониманием имени Sample.java файла, но я не могу получить само имя класса, так как это довольно сложно сделать из динамического текстового содержимого.

Ответ №2:

Вы можете справиться с этим двумя способами.

Если у вас есть последняя версия Java, вы можете просто пропустить шаг «javac» и запустить «java», и класс будет автоматически скомпилирован и автоматически запущен, даже если имя класса не совпадает с именем .java файла.

Поэтому, если бы ваш временный java-файл был сгенерирован "\Temp\XYZ.java" , он бы скомпилировался и запустился, распечатав Hello Java :

 Path fullPath = Path.of("/Temp", "XYZ.java").toAbsolutePath(); // wherever var pb = new ProcessBuilder(new String[] { "java", fullPath.toString() }); ...   

Если у вас нет последней версии Java, выполните свой шаг «javac», но запишите файл во вновь созданный каталог, используемый только для этого одного сгенерированного файла Java:

 Path fullPath = Path.of("/Temp", "wherever", "ANYNAME.java").toAbsolutePath(); var pb = new ProcessBuilder(new String[] { "javac", fullPath }); ...  

Затем просмотрите содержимое fullPath.getParent() и , чтобы найти файл с расширением .class , выведите имя класса из имени файла перед расширением файла и используйте свой шаг «java» с этим производным именем класса и с каталогом пути к классу, установленным в fullPath.getParent() . Например, второй этап будет выглядеть так:

 String fn = Files.list(fullPath.getParent()).map(Path::getFileName).map(Path::toString).filter(s -gt; s.endsWith(".class")).findFirst().get(); String className = fn.substring(0, fn.lastIndexOf('.')); var pb = new ProcessBuilder(new String[] { "java", "-cp", fullPath.getParent().toString(), className }); ...  

Комментарии:

1. спасибо за обходной путь… это временно решило мою проблему.