无法写入 AppData
Not able to write to AppData
我正在用 JavaFX 制作一个小游戏,我想要一个高分系统。
因为我不太擅长数据库,所以我将数据写入了一个文本文件。
但是那很容易编辑,所以我想把它写到 AppData 中的文本文件中。
所以我尝试了这一行:
File file = new File(System.getenv("AppData") + "\" + [Namefoler\NameFile]);
但它一直说我无权访问该文件夹。
写入和关闭文件没有问题,所以如果我只是将它写入与我的 jar 相同目录中的文本文件,我的系统工作正常。
但它不断抛出这些错误。
有人知道我该如何防止这种情况发生,或者有更好的解决方案吗?
提前致谢
此答案与 AppData 无关,但您确实询问了其他解决方案,因此这是基于 Preferences API 的解决方案。该示例用于基于偏好的 API 高分系统存储。该示例不加密数据。
您在问题中提到您担心用户修改偏好以捏造高分。为客户端应用程序加密或隐藏数据以使用户无法修改数据是一个棘手的提议,因此我不会在这里讨论如何做到这一点。如果这是您的要求,那么您可以在 Internet 上研究其他信息以找到实现该目标的方法。
ScoreStorage.java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
public class ScoreStorage {
private static final int MAX_NUM_SCORES = 3;
private static final String SCORE_PREFERENCE_KEY_PREFIX = "score-";
private ObservableList<Integer> scores = FXCollections.observableArrayList();
private Preferences scorePreferences = Preferences.userNodeForPackage(
ScoreStorage.class
);
public ScoreStorage() throws BackingStoreException {
for (String key: scorePreferences.keys()) {
scores.add(scorePreferences.getInt(key, 0));
}
}
public ObservableList<Integer> getUnmodifiableScores() {
return FXCollections.unmodifiableObservableList(scores);
}
public void clearScores() {
scores.clear();
storeScores();
}
public void recordScore(int score) {
int i = 0;
while (i < MAX_NUM_SCORES && i < scores.size() && scores.get(i) >= score) {
i++;
}
if (i < MAX_NUM_SCORES) {
if (scores.size() == MAX_NUM_SCORES) {
scores.remove(scores.size() - 1);
}
scores.add(i, score);
storeScores();
}
}
private void storeScores() {
int i = 0;
for (int score: scores) {
scorePreferences.putInt(SCORE_PREFERENCE_KEY_PREFIX + i, score);
i++;
}
while (i < MAX_NUM_SCORES) {
scorePreferences.remove(SCORE_PREFERENCE_KEY_PREFIX + i);
i++;
}
}
}
HighScoreApp.java
测试工具:
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.Random;
import java.util.prefs.BackingStoreException;
public class HighScoreApp extends Application {
private static ScoreStorage scoreStorage;
private Random random = new Random(42);
@Override
public void start(Stage stage) throws Exception {
ListView<Integer> scoreList = new ListView<>(scoreStorage.getUnmodifiableScores());
scoreList.setPrefHeight(150);
Label lastScoreLabel = new Label();
Button generateScore = new Button("Generate new score");
generateScore.setOnAction(event -> {
int lastScore = random.nextInt(11_000);
lastScoreLabel.setText("" + lastScore);
scoreStorage.recordScore(lastScore);
});
Button clearScores = new Button("Clear scores");
clearScores.setOnAction(event -> scoreStorage.clearScores());
HBox scoreGenerator = new HBox(10, generateScore, lastScoreLabel);
scoreGenerator.setAlignment(Pos.BASELINE_LEFT);
VBox layout = new VBox(10, scoreGenerator, scoreList, clearScores);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) throws BackingStoreException {
scoreStorage = new ScoreStorage();
launch(args);
}
}
我正在用 JavaFX 制作一个小游戏,我想要一个高分系统。 因为我不太擅长数据库,所以我将数据写入了一个文本文件。 但是那很容易编辑,所以我想把它写到 AppData 中的文本文件中。 所以我尝试了这一行:
File file = new File(System.getenv("AppData") + "\" + [Namefoler\NameFile]);
但它一直说我无权访问该文件夹。 写入和关闭文件没有问题,所以如果我只是将它写入与我的 jar 相同目录中的文本文件,我的系统工作正常。 但它不断抛出这些错误。
有人知道我该如何防止这种情况发生,或者有更好的解决方案吗?
提前致谢
此答案与 AppData 无关,但您确实询问了其他解决方案,因此这是基于 Preferences API 的解决方案。该示例用于基于偏好的 API 高分系统存储。该示例不加密数据。
您在问题中提到您担心用户修改偏好以捏造高分。为客户端应用程序加密或隐藏数据以使用户无法修改数据是一个棘手的提议,因此我不会在这里讨论如何做到这一点。如果这是您的要求,那么您可以在 Internet 上研究其他信息以找到实现该目标的方法。
ScoreStorage.java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
public class ScoreStorage {
private static final int MAX_NUM_SCORES = 3;
private static final String SCORE_PREFERENCE_KEY_PREFIX = "score-";
private ObservableList<Integer> scores = FXCollections.observableArrayList();
private Preferences scorePreferences = Preferences.userNodeForPackage(
ScoreStorage.class
);
public ScoreStorage() throws BackingStoreException {
for (String key: scorePreferences.keys()) {
scores.add(scorePreferences.getInt(key, 0));
}
}
public ObservableList<Integer> getUnmodifiableScores() {
return FXCollections.unmodifiableObservableList(scores);
}
public void clearScores() {
scores.clear();
storeScores();
}
public void recordScore(int score) {
int i = 0;
while (i < MAX_NUM_SCORES && i < scores.size() && scores.get(i) >= score) {
i++;
}
if (i < MAX_NUM_SCORES) {
if (scores.size() == MAX_NUM_SCORES) {
scores.remove(scores.size() - 1);
}
scores.add(i, score);
storeScores();
}
}
private void storeScores() {
int i = 0;
for (int score: scores) {
scorePreferences.putInt(SCORE_PREFERENCE_KEY_PREFIX + i, score);
i++;
}
while (i < MAX_NUM_SCORES) {
scorePreferences.remove(SCORE_PREFERENCE_KEY_PREFIX + i);
i++;
}
}
}
HighScoreApp.java
测试工具:
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.Random;
import java.util.prefs.BackingStoreException;
public class HighScoreApp extends Application {
private static ScoreStorage scoreStorage;
private Random random = new Random(42);
@Override
public void start(Stage stage) throws Exception {
ListView<Integer> scoreList = new ListView<>(scoreStorage.getUnmodifiableScores());
scoreList.setPrefHeight(150);
Label lastScoreLabel = new Label();
Button generateScore = new Button("Generate new score");
generateScore.setOnAction(event -> {
int lastScore = random.nextInt(11_000);
lastScoreLabel.setText("" + lastScore);
scoreStorage.recordScore(lastScore);
});
Button clearScores = new Button("Clear scores");
clearScores.setOnAction(event -> scoreStorage.clearScores());
HBox scoreGenerator = new HBox(10, generateScore, lastScoreLabel);
scoreGenerator.setAlignment(Pos.BASELINE_LEFT);
VBox layout = new VBox(10, scoreGenerator, scoreList, clearScores);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) throws BackingStoreException {
scoreStorage = new ScoreStorage();
launch(args);
}
}