【问题标题】:Singleton pattern with ini4j带有 ini4j 的单例模式
【发布时间】:2016-12-25 16:06:09
【问题描述】:

原始问题:程序正在读取旧配置文件 (.ini) 的输入

新问题:尝试使用流/ini 的单例模式后,我无法再写入文件。它抛出一个 java.io.FileNotFoundException。

无论如何我可以修改我的配置类以使其工作吗?

提前致谢。

配置类:

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();
        }
    }
}

部分:漂移

字段:亩

值:5

5 个无法存储。

org.ini4j.Ini.store(Ini.java:126) 处的 java.io.FileNotFoundException 在 application.prototypes.Configuration.setConfig(Configuration.java:72) 在 application.prototypes.UserInputs.lambda$0(UserInputs.java:92) 在 com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) 在 com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 在 com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 在 com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 在 com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 在 com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 在 com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 在 com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 在 com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 在 com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 在 com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 在 com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 在 javafx.event.Event.fireEvent(Event.java:198) 在 javafx.scene.Scene$KeyHandler.process(Scene.java:3964) 在 javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910) 在 javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040) 在 javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501) 在 com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:216) 在 com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:148) 在 java.security.AccessController.doPrivileged(Native Method) 在 com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$353(GlassViewEventHandler.java:247) 在 com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 在 com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:246) 在 com.sun.glass.ui.View.handleKeyEvent(View.java:546) 在 com.sun.glass.ui.View.notifyKey(View.java:966) 在 com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 在 com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 在 java.lang.Thread.run(Unknown Source)

解决新问题:请参阅下面的答案。

原始问题的解决方案:

我正在使用 Java-Runtime-Compiler 库动态加载一个类。经过一番研究,我读到 ClassLoader 只能有一个特定类的实例。因此,解决方案是在 .loadFromJava() 方法中创建一个新的 ClassLoader 实例,并解决了繁荣问题。

这里有一些代码。

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();

...

动态类实现 Callable 并返回对象 - 因此可以检索它在其中创建的任何内容。

【问题讨论】:

  • System.out.println("FILE NOT FOUND!"); 是否在运行时执行?
  • 对于单例,您可以做的更简单,无需与 Bill Pugh 的单例实现显式同步
  • @davidxxx 它正在打印“...无法存储。”
  • 好的,您可以发布与此异常相关的堆栈跟踪吗?
  • 我认为问题在于流 - 当它尝试写入时,它不再具有访问权限。我希望有办法克服这个问题。

标签: java singleton inputstream fileinputstream


【解决方案1】:

我刚刚查看了源代码。
问题是如果您想使用相同的Wini 实例来调用store() 方法,应避免Wini 类中的void load(InputStream input) 加载ini 文件。
为什么 ? 因为store() 方法希望在当前Wini 的实例中有一个现有的文件字段,但它找不到它,因为您从流而不是文件加载了ini。

所以您应该使用Wini 构造函数来加载ini 文件。构造函数以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);
    }
}

这是使用日志记录来记录异常的完整类,它使用惰性单例实现而不使用任何显式同步,如 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);         
        }
    }
}

【讨论】:

  • 非常感谢。它解决了“写入”问题,并使解决原始问题变得更加容易。如果您好奇,我在描述中添加了解释。再次感谢 - 节日快乐。
  • 好消息。我已经看到了原始问题的解决方案:有趣。不客气。也祝你节日快乐:)
猜你喜欢
  • 1970-01-01
  • 2014-08-08
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多