2016-12-31 5 views
0

У меня есть проект javafx, который я готовлю для распространения. Проект отлично работает с отладчиком внутри NetBeans. Я работаю над Linux.jar файл не обновляет значения в файле

Но когда я запускаю проект из файла jar, есть одна функция во всех остальных, которая не работает. Предполагается, что эта функция откроет файл настроек нажатием кнопки и изменит некоторые значения с true на false.

Я изменил местоположение файла настроек и попробовал Google, но все безрезультатно.

Я по-прежнему новичок в java, fx, netbeans и java (не столько программирование), сколько в своих первых впечатлениях.

Любая идея, почему это происходит?

@FXML 
private void openSettingsFile(ActionEvent event) throws IOException { 

    // this test works .... 
    ProcessBuilder processBuilder = new ProcessBuilder("terminal"); 
    processBuilder.start(); 

    // this part only replaces the values when I use the debugger .. 
    Path path = Paths.get("src/desktop_launcher/Settings.java"); 
    Charset charset = StandardCharsets.UTF_8; 
    String content = new String(Files.readAllBytes(path)); 
    content = content.replaceAll(" \"true\"" , " \"false\""); 
    Files.write(path, content.getBytes(charset)); 
+0

Что вы здесь делаете? Похоже, вы пытаетесь манипулировать * исходным * файлом и для него иметь эффект во время выполнения. Как вы компилируете файл, создаете банку и динамически загружаете класс во время выполнения? Помимо всего прочего, вы не можете ожидать, что каталог 'src' будет доступен во время выполнения. Вы знаете, что Java компилируется, правильно? –

+0

У меня есть ряд флажков, которые должны помнить, что их состояния выбраны (или нет) каждый раз, когда я ЗАКРЫВАЮ и ПЕРЕПУСКАЮ программу. Когда я закрываю приложение при изменении состояния флажка, оно должно начинаться так, как оно было закрыто. Я создал файл настроек, и указанная выше функция должна подавать файл настроек, который в свою очередь передает исходное состояние флажков. Я знаю, что расположение файла настроек не является идеальным. Но изменение папки для попытки не помогло. Является ли местоположение файла важным для работы функции? Он работает все правильно от отладчика – rainer

+0

Если это файл настроек, то почему у него есть расширение '.java'? Вы должны использовать текстовый файл, возможно, в формате, совместимом с ['java.util.Properties'] (http://docs.oracle.com/javase/8/docs/api/java/util/Properties.html). Что касается расположения файлов, папка 'src', очевидно, недоступна во время выполнения, а' Paths.get (...) 'будет разрешаться относительно рабочего каталога. Я бы рекомендовал использовать домашний каталог пользователей ('System.getProperty (« user.home »)) и создать в нем каталог и файл. –

ответ

1

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

Во-первых, исходные файлы, как правило, недоступны во время выполнения: ваш файл jar содержит файлы классов и другие ресурсы, необходимые для запуска приложения, но обычно это не исходный код (и нежелательно включать его в приложение, в общем).

Во-вторых, вы пытаетесь найти этот файл с относительного пути, пройденного до Paths.get(..). Это будет разрешено относительно рабочего каталога, который по существу произволен (в основном «где приложение было запущено»). Поэтому, даже если исходный код был доступен во время выполнения, это не был бы надежный способ его найти. (Мое предположение заключается в том, что ваш отладчик работает с рабочим каталогом, случайно установленным в родительский каталог src, но при запуске файла jar наиболее вероятным расположением рабочего каталога является каталог, в котором находится файл jar. просто угадайте: это действительно зависит от конфигурации вашей IDE, отладчика и т. д.)

В-третьих, и, возможно, самое главное, даже если код действительно находит исходный файл и переписывает его, это все, что он сделает. В следующий раз, когда вы запустите приложение из файла jar, он не будет волшебно знать, что есть новая версия исходного кода, который должен быть скомпилирован, а затем результирующий файл (ы) класса, встроенный в файл jar. Поэтому вам нужно будет также включить код для компиляции новой версии вашего исходного кода (где вы получите компилятор: AFAIK не все Java-среды будут включать компилятор), а затем программно вставить новые файлы классов в файл jar (как вы можете понять, где находится файл jar: это, конечно, нетривиально, и я не думаю, что это можно сделать надежным образом). Что делать, если текущий пользователь не имеет прав на запись каталога, содержащего банку (что довольно распространенный сценарий?)?

Обычный способ загрузки и сохранения значений конфигурации запуска заключается в использовании java.util.Properties API. Для хранения файла свойств вам нужно иметь внешнее местоположение, которое может быть определен на компьютере пользователя: удобным способом это создать каталог, предназначенный для приложения, в домашнем каталоге пользователя. Доступ к домашнему каталогу пользователя можно получить через System.getProperty("user.home"); (Системное свойство user.home является одним из тех, что является guaranteed to exist.).

Я бы рекомендовал использовать отдельный класс для управления свойствами конфигурации. Например:

И теперь вы можете использовать его в своем приложении.Просто загрузите свойства в методе init() и сохраните их обратно в методе stop(). Обратите внимание, что при выполнении этого будет создан каталог с именем .myApp в вашем домашнем каталоге и файл с именем startup.properties внутри него.

import java.io.IOException; 

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.CheckBox; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

public class StartupPropertiesExample extends Application { 

    private PropertiesAccessor config ; 

    private CheckBox value1 ; 
    private CheckBox value2 ; 

    @Override 
    public void init() { 
     config = new PropertiesAccessor(".myApp/startup.properties"); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     value1 = new CheckBox("Value 1"); 
     value2 = new CheckBox("Value 2"); 
     value1.setSelected(config.getBooleanValue("config.value1")); 
     value2.setSelected(config.getBooleanValue("config.value2")); 

     Button exit = new Button("Exit"); 
     exit.setOnAction(e -> Platform.exit()); 

     VBox root = new VBox(10, value1, value2, exit); 
     root.setPadding(new Insets(10)); 

     Scene scene = new Scene(root); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    @Override 
    public void stop() { 
     config.updateBooleanValue("config.value1", value1.isSelected()); 
     config.updateBooleanValue("config.value2", value2.isSelected()); 
     try { 
      config.writeProperties(); 
     } catch (IOException exc) { 
      System.err.println("Warning: could not save properties"); 
      exc.printStackTrace(System.err); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

Джеймс, большое спасибо за ваши ценные и технические советы. Ваши наблюдения действительно отвечают на множество вопросов, которые у меня были о java-фондах ... (другие приходят ..). Я пробовал метод Get.Path с другими папками, и он действительно не работал хорошо. И мой главный интерес к хранению и извлечению правильных значений настроек стал ясным, и решение очень элегантно. Большое спасибо за время и терпение, чтобы изучить этот вопрос и ответить так широко. – rainer

+0

James, почему это строка «config.updateBooleanValue (« config.value1 », value1.isSelected());» работает только в методе остановки? – rainer

+0

@Rainer не уверен, что я понимаю вопрос. Код в методе остановки обновляет свойства с новыми значениями из пользовательского интерфейса и сохраняет их в файл свойств. Вам не нужно делать это, пока программа не выйдет. –