ini4j 的单例模式
Singleton pattern with ini4j
原问题:程序正在读取旧配置文件 (.ini) 的输入
新问题:尝试使用 stream/ini 的单例模式后,我无法再写入文件。它抛出 java.io.FileNotFoundException.
我是否可以修改我的配置 class 使其正常工作?
提前致谢。
配置class:
import org.ini4j.Wini;
import java.io.*;
//http://www.javenue.info/post/40
public class Configuration {
private static Configuration _instance = null;
private Wini ini = null;
FileInputStream stream;
private Configuration() {
ini= new Wini();
try {
stream = new FileInputStream(Constants.PATH);
ini.load(stream);
}
catch (Exception e) {
System.out.println("FILE NOT FOUND!");
}
}
public synchronized static Configuration getInstance() {
if (_instance == null)
_instance = new Configuration();
return _instance;
}
public String getConfig(String xSectionName, String xFieldValue){
String readValue = null;
if (ini.get(xSectionName, xFieldValue) != null) {
readValue = ini.get(xSectionName, xFieldValue);
} else {
// TODO: What should happen
}
return readValue;
}
public void setConfig(String xSectionName, String xFieldValue, String xValue){
System.out.println("Section: " + xSectionName);
System.out.println("Field: " + xFieldValue);
System.out.println("Value: " + xValue + "\n\n");
try {
ini.put(xSectionName, xFieldValue, xValue);
ini.store();
} catch (Exception e1) {
System.out.println(xValue + " could not be stored.");
e1.printStackTrace();
}
}
}
Section: drift
Field: mu
Value: 5
5 could not be stored.
java.io.FileNotFoundException at org.ini4j.Ini.store(Ini.java:126)
at
application.prototypes.Configuration.setConfig(Configuration.java:72)
at application.prototypes.UserInputs.lambda[=12=](UserInputs.java:92) at
com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at
com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at
com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at
com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at
com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at
com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at
com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at
com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at
javafx.event.Event.fireEvent(Event.java:198) at
javafx.scene.Scene$KeyHandler.process(Scene.java:3964) at
javafx.scene.Scene$KeyHandler.access00(Scene.java:3910) at
javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040) at
javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501) at
com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:216)
at
com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:148)
at java.security.AccessController.doPrivileged(Native Method) at
com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent3(GlassViewEventHandler.java:247)
at
com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at
com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:246)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546) at
com.sun.glass.ui.View.notifyKey(View.java:966) at
com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at
com.sun.glass.ui.win.WinApplication.lambda$null8(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)
新问题的解决方案:请参阅下面的答案。
原始问题的解决方案:
我正在使用 Java-Runtime-Compiler 库动态加载 class。经过一些研究,我读到一个 ClassLoader 只能有一个特定 class 的实例。因此,解决方案是在 .loadFromJava() 方法中创建一个 ClassLoader 的新实例,然后 boom 问题就解决了。
这是一些代码。
import net.openhft.compiler.CompilerUtils;
...
ClassLoader classloader = new ClassLoader() {
};
Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(classloader, className, javaCode);
Callable<Object[]> caller = (Callable<Object[]>) aClass.newInstance();
Object[] obj = (Object[]) caller.call();
...
动态 class 实现 Callable 和 returns 对象 - 因此可以检索它在其中创建的任何内容。
我刚刚查看了源代码。
问题是Wini
中的void load(InputStream input)
class如果要使用相同的Wini
实例调用store()
方法应该避免加载ini文件.
为什么 ?
因为 store()
方法期望在当前 Wini
的实例中有一个现有的文件字段,但是它找不到它,因为您从流而不是文件加载了 ini。
所以你应该使用 Wini
构造函数加载 ini 文件。构造函数以 a File
作为参数,它还额外设置实例中的字段以加载 ini 内容。
看看这个:
public Wini(File input) throws IOException, InvalidFileFormatException{
this();
setFile(input);
load();
}
所以替换:
private Configuration() {
ini = new Wini();
try {
stream = new FileInputStream(Constants.PATH);
ini.load(stream);
}
catch (Exception e) {
System.out.println("FILE NOT FOUND!");
}
}
通过这个 :
private Configuration() {
try {
ini= new Wini(new File(Constants.PATH));
}
catch (Exception e) {
LOGGER.error("Exception during init of Configuration",e);
}
}
这是完整的 class 使用日志记录来记录异常,它使用惰性单例实现而不使用任何显式同步 synchronized
:
public class Configuration {
private static Logger LOGGER = Logger.getLogger(Configuration.class)//
private static class HolderLazySingleton {
private static Configuration instance = new Configuration();
}
private Wini ini = null;
private Configuration() {
try {
ini = new Wini(new File(Constants.PATH));
} catch (Exception e) {
LOGGER.error("Exception during init of Configuration",e);
}
}
public static Configuration getInstance() {
return HolderLazySingleton.instance;
}
public String getConfig(String xSectionName, String xFieldValue) {
String readValue = null;
if (ini.get(xSectionName, xFieldValue) != null) {
readValue = ini.get(xSectionName, xFieldValue);
} else {
// TODO: What should happen
}
return readValue;
}
public void setConfig(String xSectionName, String xFieldValue, String xValue) {
System.out.println("Section: " + xSectionName);
System.out.println("Field: " + xFieldValue);
System.out.println("Value: " + xValue + "\n\n");
try {
ini.put(xSectionName, xFieldValue, xValue);
ini.store();
} catch (Exception e1) {
LOGGER.error(xValue + " could not be stored.", e1);
}
}
}
原问题:程序正在读取旧配置文件 (.ini) 的输入
新问题:尝试使用 stream/ini 的单例模式后,我无法再写入文件。它抛出 java.io.FileNotFoundException.
我是否可以修改我的配置 class 使其正常工作?
提前致谢。
配置class:
import org.ini4j.Wini;
import java.io.*;
//http://www.javenue.info/post/40
public class Configuration {
private static Configuration _instance = null;
private Wini ini = null;
FileInputStream stream;
private Configuration() {
ini= new Wini();
try {
stream = new FileInputStream(Constants.PATH);
ini.load(stream);
}
catch (Exception e) {
System.out.println("FILE NOT FOUND!");
}
}
public synchronized static Configuration getInstance() {
if (_instance == null)
_instance = new Configuration();
return _instance;
}
public String getConfig(String xSectionName, String xFieldValue){
String readValue = null;
if (ini.get(xSectionName, xFieldValue) != null) {
readValue = ini.get(xSectionName, xFieldValue);
} else {
// TODO: What should happen
}
return readValue;
}
public void setConfig(String xSectionName, String xFieldValue, String xValue){
System.out.println("Section: " + xSectionName);
System.out.println("Field: " + xFieldValue);
System.out.println("Value: " + xValue + "\n\n");
try {
ini.put(xSectionName, xFieldValue, xValue);
ini.store();
} catch (Exception e1) {
System.out.println(xValue + " could not be stored.");
e1.printStackTrace();
}
}
}
Section: drift
Field: mu
Value: 5
5 could not be stored.
java.io.FileNotFoundException at org.ini4j.Ini.store(Ini.java:126) at application.prototypes.Configuration.setConfig(Configuration.java:72) at application.prototypes.UserInputs.lambda[=12=](UserInputs.java:92) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$KeyHandler.process(Scene.java:3964) at javafx.scene.Scene$KeyHandler.access00(Scene.java:3910) at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040) at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501) at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:216) at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:148) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent3(GlassViewEventHandler.java:247) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:246) at com.sun.glass.ui.View.handleKeyEvent(View.java:546) at com.sun.glass.ui.View.notifyKey(View.java:966) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null8(WinApplication.java:191) at java.lang.Thread.run(Unknown Source)
新问题的解决方案:请参阅下面的答案。
原始问题的解决方案:
我正在使用 Java-Runtime-Compiler 库动态加载 class。经过一些研究,我读到一个 ClassLoader 只能有一个特定 class 的实例。因此,解决方案是在 .loadFromJava() 方法中创建一个 ClassLoader 的新实例,然后 boom 问题就解决了。
这是一些代码。
import net.openhft.compiler.CompilerUtils;
...
ClassLoader classloader = new ClassLoader() {
};
Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(classloader, className, javaCode);
Callable<Object[]> caller = (Callable<Object[]>) aClass.newInstance();
Object[] obj = (Object[]) caller.call();
...
动态 class 实现 Callable 和 returns 对象 - 因此可以检索它在其中创建的任何内容。
我刚刚查看了源代码。
问题是Wini
中的void load(InputStream input)
class如果要使用相同的Wini
实例调用store()
方法应该避免加载ini文件.
为什么 ?
因为 store()
方法期望在当前 Wini
的实例中有一个现有的文件字段,但是它找不到它,因为您从流而不是文件加载了 ini。
所以你应该使用 Wini
构造函数加载 ini 文件。构造函数以 a File
作为参数,它还额外设置实例中的字段以加载 ini 内容。
看看这个:
public Wini(File input) throws IOException, InvalidFileFormatException{
this();
setFile(input);
load();
}
所以替换:
private Configuration() {
ini = new Wini();
try {
stream = new FileInputStream(Constants.PATH);
ini.load(stream);
}
catch (Exception e) {
System.out.println("FILE NOT FOUND!");
}
}
通过这个 :
private Configuration() {
try {
ini= new Wini(new File(Constants.PATH));
}
catch (Exception e) {
LOGGER.error("Exception during init of Configuration",e);
}
}
这是完整的 class 使用日志记录来记录异常,它使用惰性单例实现而不使用任何显式同步 synchronized
:
public class Configuration {
private static Logger LOGGER = Logger.getLogger(Configuration.class)//
private static class HolderLazySingleton {
private static Configuration instance = new Configuration();
}
private Wini ini = null;
private Configuration() {
try {
ini = new Wini(new File(Constants.PATH));
} catch (Exception e) {
LOGGER.error("Exception during init of Configuration",e);
}
}
public static Configuration getInstance() {
return HolderLazySingleton.instance;
}
public String getConfig(String xSectionName, String xFieldValue) {
String readValue = null;
if (ini.get(xSectionName, xFieldValue) != null) {
readValue = ini.get(xSectionName, xFieldValue);
} else {
// TODO: What should happen
}
return readValue;
}
public void setConfig(String xSectionName, String xFieldValue, String xValue) {
System.out.println("Section: " + xSectionName);
System.out.println("Field: " + xFieldValue);
System.out.println("Value: " + xValue + "\n\n");
try {
ini.put(xSectionName, xFieldValue, xValue);
ini.store();
} catch (Exception e1) {
LOGGER.error(xValue + " could not be stored.", e1);
}
}
}