英文:
java program (with txt/csv) works fine in IDE but not in jar
问题
// userDatabaseHandler.java
public class userDatabaseHandler {
public userDatabaseHandler() {
fileName = "src/sample/database/users.csv";
// ...
try {
InputStream inputStream = getClass().getResourceAsStream("/sample/database/users.csv");
Scanner scanner = new Scanner(inputStream);
scanner.nextLine(); // ignores first line
// ...
} catch (Exception e) {
// ...
}
// ...
}
// ...
}
// taskDatabaseHandler.java
public class taskDatabaseHandler {
public taskDatabaseHandler() {
fileName = "src/sample/database/tasks.csv";
// ...
try {
InputStream inputStream = getClass().getResourceAsStream("/sample/database/tasks.csv");
Scanner scanner = new Scanner(inputStream);
<details>
<summary>英文:</summary>
<br>
I'm currently trying to create an executable jar of a todolist-app I developed in Intellij. I use a CSV file to store the users and tasks, and a txt file to store the current user. Although I've been able to run the program on my IDE, when I try to run it through command prompt on windows I get this error:
***Error:*** <br>
C:\WINDOWS\system32>java --module-path C:\JavaFX\javafx-sdk-14.0.2.1\lib --add-modules javafx.controls,javafx.fxml -jar C:\Users\jkcar\IdeaProjects\toDoList\out\artifacts\toDoList_jar\toDoList.jar
java.io.FileNotFoundException: toDoList.jar\sample\database\users.csv (The system cannot find the path specified)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:212)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:154)
at java.base/java.util.Scanner.<init>(Scanner.java:639)
at sample.database.userDatabaseHandler.<init>(userDatabaseHandler.java:23)
at sample.controller.loginController.initialize(loginController.java:46)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2591)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at sample.Main.start(Main.java:13)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
UserDatabase with 0 rows initialized
java.nio.file.NoSuchFileException: toDoList.jar\sample\database\loggedInUser.txt
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
at java.base/sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:235)
at java.base/java.nio.file.Files.newByteChannel(Files.java:375)
at java.base/java.nio.file.Files.newByteChannel(Files.java:426)
at java.base/java.nio.file.Files.readAllBytes(Files.java:3272)
at java.base/java.nio.file.Files.readString(Files.java:3350)
at java.base/java.nio.file.Files.readString(Files.java:3309)
at sample.database.currentUser.<init>(currentUser.java:19)
at sample.database.userDatabaseHandler.<init>(userDatabaseHandler.java:48)
at sample.controller.loginController.initialize(loginController.java:46)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:273)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2591)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
at sample.Main.start(Main.java:13)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Searching for user with UID: null
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
I noticed that the errors have to do with the program not being able to find the csv/txt files I request in the constructors of my userDatabaseHandler.java taskDatabaseHandler.java and currentUserHandler.java classes listed below.<br>
***userDatabaseHandler.java***<br>
package sample.database;
import javax.swing.*;
import java.io.*;
import java.util.*;
public class userDatabaseHandler {
//INSTANCE VARIABLES
private ArrayList<user> allUsers = new ArrayList<>();
private ArrayList<String[]> rawDataRows= new ArrayList<>();
private String fileName;
private user loggedInUser;
//CONSTRUCTOR
public userDatabaseHandler(){
fileName = "src/sample/database/users.csv";
File file = new File(fileName);
try{
Scanner inputStream = new Scanner(file);
inputStream.nextLine(); //ignores first line
//DATAROWS SIZE IS 0 HERE
while (inputStream.hasNext()){
String data = inputStream.nextLine(); //gets whole line
String[] values = data.split(","); //splits by commas
rawDataRows.add(values); //adds the line to an arraylist (dataRows)
}
inputStream.close();
} catch (FileNotFoundException e){
JOptionPane.showMessageDialog(null, "userDatabaseHandler Constructor error");
e.printStackTrace();
}
System.out.println("UserDatabase with "+rawDataRows.size()+" rows initialized");
System.out.println();
//Creation of each User
for(int i=0; i<rawDataRows.size();i++){
user tempUser = new user (rawDataRows.get(i)[0], rawDataRows.get(i)[1], rawDataRows.get(i)[2], rawDataRows.get(i)[3], rawDataRows.get(i)[4], rawDataRows.get(i)[5], rawDataRows.get(i)[6]);
//add each tweet to the allTweets array
allUsers.add(tempUser);
}
//Set Logged in User
currentUserHandler cUserHandler = new currentUserHandler();
loggedInUser = getUserByUID(cUserHandler.getCurrentUserID());
}
//GETTERS
public String getCurrentUsersID(){
return this.loggedInUser.getUserIDAsString();
}
//METHODS
//Sign Up user
public void addUser(String userID, String firstName, String lastName, String username, String password, String location, String gender){
//ADD USER TO userDatabase CLASS
/*
user newUser = new user(userID, firstName, lastName, username, password, location, gender);
allUsers.add(newUser);
*/
//ADD USER TO user.csv FILE
try{
FileWriter fw = new FileWriter(fileName, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
//Check if any sign-up fields are blank
if(firstName.equals("") || lastName.equals("") || username.equals("") || password.equals("") || location.equals("")) {
//If blank show error and return (don't sign up user)
JOptionPane.showMessageDialog(null, "Error: Fill all fields");
pw.flush();
pw.close();
return;
}else{
//If all fields filled
pw.println(userID + "," + firstName + "," + lastName + "," + username + "," + password + "," + location + "," + gender);
pw.flush();
pw.close();
}
}catch (Exception E){
JOptionPane.showMessageDialog(null, "User NOT SAVED");
}
}
public int getNumUsers(){
return (allUsers.size());
}
public boolean isUserReal(String inUsername, String inPassword){
if(!inUsername.equals("") || !inPassword.equals("")){
for(int i = 0; i<allUsers.size(); i++) {
if (allUsers.get(i).getUsername().equals(inUsername)) {
if(allUsers.get(i).getPassword().equals(inPassword)){
return true;
}
}
}
}else{
return false;
}
return false;
}
public user getUserByUID(String aUserID){
System.out.println("Searching for user with UID: "+aUserID);
for(int i = 0; i<allUsers.size(); i++){
if(aUserID.equals(allUsers.get(i).getUserIDAsString())){
return allUsers.get(i);
}
}
JOptionPane.showMessageDialog(null, "userDatabaseHandler.getUserByUID() ERROR! No User found");
return allUsers.get(0);
}
public user getUserByUserName(String Username){
for(int i = 0; i<rawDataRows.size(); i++){
if(Username.equals(rawDataRows.get(i)[3])){
return allUsers.get(i);
}
}
JOptionPane.showMessageDialog(null, "userDatabaseHandler.getUserByUserName() ERROR! No User found");
return allUsers.get(0);
}
public void LogOutAllUser(){
try{
FileWriter fw = new FileWriter("/sample/database/loggedInUser.txt", false);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
pw.print("0");
pw.flush();
pw.close();
}catch (Exception E){
JOptionPane.showMessageDialog(null, "User NOT Logged Out");
}
}
}
***taskDatabaseHandler.java***<br>
package sample.database;
import javax.swing.*;
import java.io.*;
import java.util.*;
public class taskDatabaseHandler {
//INSTANCE VARIABLES
private ArrayList<task> allTasks = new ArrayList<>();
private ArrayList<String[]> rawDataRows= new ArrayList<>();
private ArrayList<String> rawRawDataRows = new ArrayList<>();
private String fileName;
private user loggedInUser;
//CONSTRUCTOR
public taskDatabaseHandler(){
fileName="src/sample/database/tasks.csv";
File file = new File(fileName);
try{
Scanner inputStream = new Scanner(file);
inputStream.nextLine(); //ignores first line
while (inputStream.hasNext()){
String data = inputStream.nextLine(); //gets whole line
rawRawDataRows.add(data);
String[] values = data.split(","); //splits by commas
rawDataRows.add(values); //adds the line to an arraylist (dataRows)
}
inputStream.close();
} catch (FileNotFoundException e){
JOptionPane.showMessageDialog(null, "taskDatabase Constructor error");
e.printStackTrace();
}
System.out.println("TaskDatabase with " + rawDataRows.size()+ " rows initialized");
System.out.println();
//Creation of each Task
for(int i=0; i<rawDataRows.size();i++){
task tempTask = new task (rawDataRows.get(i)[0], rawDataRows.get(i)[1], rawDataRows.get(i)[2], rawDataRows.get(i)[3]);
//add each tweet to the allTweets array
allTasks.add(tempTask);
}
//Set Logged in User
currentUserHandler cUserHandler = new currentUserHandler();
userDatabaseHandler genesisUBH = new userDatabaseHandler();
loggedInUser = genesisUBH.getUserByUID(cUserHandler.getCurrentUserID());
}
//GETTERS
public String getCurrentUsersID(){
return this.loggedInUser.getUserIDAsString(); //Problem Here
}
//METHODS
public ArrayList<task> getCurrUserTasks(){
return getAllTaskByUID(getCurrentUsersID());
}
public void addTask(task iTask){
//ADD USER TO tasks.csv FILE
try{
FileWriter fw = new FileWriter(fileName, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
//Check if any sign-up fields are blank
if(iTask.getTaskIDAsString().equals("") || iTask.getUserIDAsString().equals("") || iTask.getDueDate().equals("") || iTask.getDescription().equals("")) {
//If blank show error and return (don't sign up user)
JOptionPane.showMessageDialog(null, "Error: Empty Task");
pw.flush();
pw.close();
return;
}else{
//If all fields filled
allTasks.add(iTask);
rawDataRows.add(iTask.getRawData());
rawRawDataRows.add(iTask.getRawRawData());
pw.println(iTask.getTaskID() + "," + iTask.getUserID() + "," + iTask.getDueDate() + "," + iTask.getDescription());
pw.flush();
pw.close();
}
}catch (Exception E){
JOptionPane.showMessageDialog(null, "Task NOT SAVED");
}
}
public int getNextTaskID(){
int highestID = 0;
for(int i =0;i<allTasks.size();i++){
if(allTasks.get(i).getTaskID()>highestID){
highestID = allTasks.get(i).getTaskID();
}
}
return (highestID+1);
}
public void removeTask(task inputTask){
for(int i = 0; i<rawDataRows.size(); i++){
if(allTasks.get(i).equals(inputTask)){
//Remove Task
removeLineFromFile("/sample/database/tasks.csv", rawRawDataRows.get(i));
allTasks.remove(i);
rawDataRows.remove(i);
rawRawDataRows.remove(i);
return;
}
}
}
public ArrayList<task> getAllTaskByUID(String UserID){
ArrayList<task> allRetTasks = new ArrayList<task>();
for(int i = 0; i<allTasks.size(); i++){
if(UserID.equals(allTasks.get(i).getUserIDAsString())){
allRetTasks.add(allTasks.get(i));
}
}
return allRetTasks;
}
public task getAllTaskByDescription(String Description){
for(int i = 0; i<rawDataRows.size(); i++){
if(Description.equals(allTasks.get(i).getDescription())){
return allTasks.get(i);
}
}
return allTasks.get(1);
}
public void removeLineFromFile(String file, String lineToRemove) {
try {
File inFile = new File(file);
if (!inFile.isFile()) {
System.out.println("'"+lineToRemove+"' is not an existing file");
return;
}
//Construct the new file that will later be renamed to the original filename.
File tempFile = new File(inFile.getAbsolutePath() + ".tmp");
BufferedReader br = new BufferedReader(new FileReader(file));
PrintWriter pw = new PrintWriter(new FileWriter(tempFile));
String line = null;
//Read from the original file and write to the new
//unless content matches data to be removed.
while ((line = br.readLine()) != null) {
if (!line.trim().equals(lineToRemove)) {
pw.println(line);
pw.flush();
}
}
pw.close();
br.close();
//Delete the original file
if (!inFile.delete()) {
System.out.println("Could not delete file");
return;
}
//Rename the new file to the filename the original file had.
if (!tempFile.renameTo(inFile))
System.out.println("Could not rename file");
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
***currentUserHandler.java***<br>
package sample.database;
import javax.swing.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class currentUserHandler {
//INSTANCE VARIABLES
String fileName;
String currentUserID;
//CONSTRUCTER
public currentUserHandler(){
fileName = "src/sample/database/loggedInUser.txt";
File loggedInUserFile = new File(fileName);
try{
String text = Files.readString(Paths.get(fileName));
if(!text.equals("")) {
String loggedInUserID = text; //gets the logged in user
currentUserID = loggedInUserID;
}else{
currentUserID = "0";
}
} catch (FileNotFoundException e){
JOptionPane.showMessageDialog(null, "Error Setting Logged in User");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//GETTERS
public String getCurrentUserID(){
return this.currentUserID;
}
//SETTERS
public void setCurrentUserID(String newID){
this.currentUserID = newID;
try{
FileWriter fw = new FileWriter(fileName, false);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
pw.print(newID);
//JOptionPane.showMessageDialog(null, "LoggedInUserSaved");
pw.flush();
pw.close();
}catch (Exception E){
JOptionPane.showMessageDialog(null, "LoggedInUser Not Saved");
}
}
}
***FilePaths***<br>
[IDE Filepaths][1]
I was wondering if anyone has any recommendations on how to reformat my constructors (specifically the File declaration at the beginning of each) so they will run in the jar and IDE. Thank you for any help you can give
[1]: https://i.stack.imgur.com/XGx1a.jpg
</details>
# 答案1
**得分**: 1
谢谢大家的帮助,<br>
结果发现在JAR文件中无法写入任何文件(例如:txt和csv)。 JAR文件被锁定,一旦创建就无法编辑。为了解决我的问题,我将txt和csv文件移动到了C://驱动器下的新文件夹中,并在处理程序中将路径更改为它们的路径。
<details>
<summary>英文:</summary>
Thank you all for your help,<br>
Turns out that writing to any file (ie: txt and csv) doesn't work within a JAR. JARs are locked and can't be edited once created. To fix my problem I just moved my txt and csv files into a new folder under my C:// drive and changed the path to them in my handlers.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论