我为需要创建和更新的JavaFX桌面应用程序提供了两个XML文件。经过一些研究,我发现JAXB是一个简单的解析器。
现在阅读工作正常,但是当我尝试更新XML元素时,它会引发异常:
线程“main”中的异常java.io.FileNotFoundException: \ storage \ device.xml(系统找不到指定的路径)
我还尝试使用属性文件,但这与我需要的层次结构不相符。
JAXB不是更新XML文件中现有元素的方法,还是在这种情况下是否需要使用DOM解析器?
现在我已经挣扎了几个小时没有任何解决方案。 我使用maven和XML文件存储在资源文件夹内的存储文件夹中。 有关详细信息,请参阅下面的代码示例。
欢迎所有反馈,建议或解决此问题的其他解决方案(其他存储解决方案?)等。
也许您知道处理这两个XML文件的更好解决方案吗?
提前谢谢!
DeviceDemo.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class DeviceDemo {
public static void main(String[] args) throws Exception {
// Initialize
String file = "/storage/device.xml";
JAXBContext jaxbContext = JAXBContext.newInstance(Device.class);
// Read
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = DeviceDemo.class.getResourceAsStream(file);
Device device = (Device) unmarshaller.unmarshal(inputStream);
inputStream.close();
// Update
device.setName("Updated name");
device.setHost("Updated host");
device.setPort(2302);
Marshaller marshaller = jaxbContext.createMarshaller();
OutputStream outputStream = new FileOutputStream(file);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(device, outputStream);
outputStream.close();
}
}
设备
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "device")
@XmlType(propOrder = {
"name",
"host",
"port"
})
public class Device {
private String name;
private String host;
private Integer port;
public String getName() {
return name;
}
@XmlElement(name = "name")
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
@XmlElement(name = "host")
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
@XmlElement(name = "port")
public void setPort(Integer port) {
this.port = port;
}
@Override
public String toString() {
return name + " " + host + " " + port;
}
}
Device.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<device>
<name>Device</name>
<host>host.com</host>
<port>80</port>
</device>
CommandsDemo.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class CommandsDemo {
public static void main(String[] args) throws Exception {
// Initialize
String file = "/storage/commands.xml";
JAXBContext jaxbContext = JAXBContext.newInstance(Commands.class);
// Read
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = CommandsDemo.class.getResourceAsStream(file);
Commands commands = (Commands) unmarshaller.unmarshal(inputStream);
inputStream.close();
// Print all commands
List<Command> commandsList = commands.getCommands();
for (Command command : commandsList) {
System.out.println(command.toString());
}
// Update a specific command
for (Command command : commandsList) {
if (command.getName().equals("Power on")) {
command.setName("Updated name");
command.setHost("Updated host");
command.setUser("Updated user");
command.setPassword("Updated password");
command.setTimeout(3439);
command.setPort(33223);
command.setCommand("Updated command");
Marshaller marshaller = jaxbContext.createMarshaller();
OutputStream outputStream = new FileOutputStream(file);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(command, outputStream);
outputStream.close();
}
}
}
}
Commands.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "commands")
public class Commands {
private List<Command> commands;
public List<Command> getCommands() {
return commands;
}
@XmlElement(name = "command")
public void setCommands(List<Command> commands) {
this.commands = commands;
}
@Override
public String toString() {
return commands.toString();
}
}
Command.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "command")
@XmlType(propOrder = {
"name",
"host",
"user",
"password",
"port",
"timeout",
"command"
})
public class Command {
private String name;
private String host;
private String user;
private String password;
private Integer port;
private Integer timeout;
private String command;
public String getName() {
return name;
}
@XmlElement(name = "name")
public void setName(String name) {
this.name = name;
}
public String getHost() {
return host;
}
@XmlElement(name = "host")
public void setHost(String host) {
this.host = host;
}
public String getUser() {
return user;
}
@XmlElement(name = "user")
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
@XmlElement(name = "password")
public void setPassword(String password) {
this.password = password;
}
public Integer getPort() {
return port;
}
@XmlElement(name = "port")
public void setPort(Integer port) {
this.port = port;
}
public Integer getTimeout() {
return timeout;
}
@XmlElement(name = "timeout")
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public String getCommand() {
return command;
}
@XmlElement(name = "command")
public void setCommand(String command) {
this.command = command;
}
@Override
public String toString() {
return name + " " + host + " " + user + " " + password + " " + port + " " + timeout + " " + command;
}
}
Commands.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<commands>
<command>
<name>Power on</name>
<host>host.com</host>
<user>user</user>
<password>password</password>
<port>22</port>
<timeout>10000</timeout>
<command>power on commando</command>
</command>
<command>
<name>Power off</name>
<host>host.com</host>
<user>user</user>
<password>password</password>
<port>22</port>
<timeout>10000</timeout>
<command>power off command</command>
</command>
</commands>
答案 0 :(得分:1)
加载XML文件时,您使用的是getResourceAsStream
。这将查找相对于类文件位置的文件/storage/device.xml
,或者当前目录。我现在记不清楚了。
当您尝试保存文件时,您使用的是名为FileOutputStream
的{{1}}。在这种情况下,它将相对于文件系统的根目录。如果您没有目录/storage/device.xml
,则系统无法保存您的文件。
示例DeviceDemo
/storage