【问题标题】:Creating a class to wrap Properties创建一个类来包装属性
【发布时间】:2018-03-05 07:12:11
【问题描述】:

我想创建一个包装属性并专门隐藏文件 I/O 操作的类。我想出了下面的删节代码。这旨在从类路径之外的固定位置的文件中读取属性。它还具有将属性写入同一文件的方法。

    //
 /* Defines key properties of the iFlag application.
  * Methods read and write properties.
 */

public  class ClientProperties {
    private Properties props;
    private static String xPanelSizeStg = "32"; 
    private static int    xPanelSize = 32;
    private static String configFilename = "/home/myname/config/client_config.properties";  

    public ClientProperties() {
        props = new Properties();
    }


  /**
     * Reads properties from file
     * Reads the current properties object from file.
     * The file is stored in /home/mimibox/config/flag_config.properties
     */            

    public  Properties readPropertiesFromFile( ){
        // create and load default properties
        InputStream input = null;
        logger.trace("Read flag config properties.");
        try {
            input = new FileInputStream( configFilename );
            //load a properties file from class path, inside static method     
            props.load(input);
            //get the property values and save
            xPanelSizeStg =  props.getProperty("xPanelsize","32");
            yPanelSizeStg =  props.getProperty("yPanelsize", "32");
         } 
        catch (IOException ex) {
            logger.error("Could not open config file" + configFilename,ex );
        } 
        finally{
            if(input!=null){
                try {
                  input.close();
                } 
                catch (IOException e) {
                logger.error( "Could not close config file" + configFilename,e );
                }
            }
        }
        return props;
    }
    /**
     * Writes properties to file
     * Writes the current properties object to file.
     * The file is stored in /home/mimibox/config/flag_config.properties
     */

    public void writePropertiesToFile() {
   //saves the current properties to file.  Overwrites the existing properties.
    Properties props = new Properties(); //a list of properties
    OutputStream outStrm = null;
    logger.info("Writing default flag config properties.");
                 System.out.println("Panel size x = " + xPanelSizeStg );
    try {
        outStrm = new FileOutputStream( configFilename );
        // set the properties values
        props.setProperty("xPanelsize", xPanelSizeStg);
        props.setProperty("yPanelsize", yPanelSizeStg);
         // save properties to file, include a header comment 
        props.store(outStrm, "This is the Server configuration file");

        } catch (IOException io) {
            logger.error( "The file :{0} could not be opened", configFilename,io);
        } finally {
            if (outStrm!= null) {
                try {
                    outStrm.close();
                } catch (IOException e) {
                  logger.error("The file :{0} could not be closed", configFilename, e);
                }
            }
        }
    } 
}

读取和写入方法有效。不起作用的是尝试更改属性的值,然后保存它。下面的演示代码成功读取了属性文件并显示了 XPanelsize 的正确值。 然后我更改该值并尝试将属性写入文件。 xPanelsize 的新值 64 未写入文件。

    public static void main(String[] args) {
    Properties props;
    ClientProperties p = new ClientProperties();
    props = p.readPropertiesFromFile(); 
    String txt = props.getProperty("xPanelsize");
         System.out.println("Panel size x = " + txt );
    p.setProperty("xPanelsize","64");  //method not found error
    p.writePropertiesToFile();

所以我希望能够使用 Property.setProperty() 方法来设置属性的值。当我这样做时,更改的属性不会写入文件。我可以看到这是因为我有超过 1 个 Property 实例,而一个对另一个不可见。我想我需要扩展内置的 Properties 类来实现我想要做的事情,但我不确定如何让它全部工作。

我在互联网上找到了大量使用属性的示例。我还没有找到任何在类中隐藏相关文件 I/O 的示例。我该怎么做?

【问题讨论】:

  • 1. Yoy 应该调用 props.setProperty() 而不是 p.setProperty()。 2. U 在 writePropertiesToFile() 方法中用旧值覆盖了相同的键“xPanelsize”,所以它没有得到反映。
  • 你知道java.util.ResourceBundle吗?
  • 只是模糊的。不够好,不能考虑使用它。
  • @dazz 还不足以考虑使用它而不是完全重新实现它?这里有一个提示:get 意识到它。它是您问题的解决方案。它包装了Properties,它对你隐藏了 I/O。

标签: java extend properties-file


【解决方案1】:

好的,感谢上面的 cmets 和答案,我做了一些更改。为了那些偶然发现这篇文章的人的利益,我在这个答案中发布了工作代码。主要变化是扩展属性。这让我可以直接使用 Properties 方法。

package com.test;

import java.util.Properties;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;

public  class ClientProperties  extends Properties {

    //initiate  logger

    private final static Logger logger = LogManager.getLogger();

    private static String xPanelSizeStg = "32";   
    private static String yPanelSizeStg = "32"; 
    private final configFilename = "/home/myname/myConfig.properties";

    public ClientProperties() {

    }


    public  Properties readPropertiesFromFile( ){
        // create and load default properties
        InputStream input = null;
        logger.trace("Read flag config properties.");
        try {
            input = new FileInputStream( configFilename );
            //load a properties file from class path, inside static method     
            this.load(input);
            //get the property values and save
            xPanelSizeStg =  this.getProperty("xPanelsize","32");
            yPanelSizeStg =  this.getProperty("yPanelsize", "32");
        } 
        catch (IOException ex) {
            logger.error("Could not open config file" + configFilename,ex );
        } 
        finally{
            if(input!=null){
                try {
                  input.close();
                } 
                catch (IOException e) {
                logger.error( "Could not close config file" + configFilename,e );
                }
            }
        }
        return this;
    }

    public void writePropertiesToFile() {
   //saves the current properties to file.  Overwrites the existing properties.
    //Properties props = new Properties(); //a list of properties
    OutputStream outStrm = null;
    logger.info("Writing default flag config properties.");
                 System.out.println("Panel size x = " + xPanelSizeStg );
    try {
        outStrm = new FileOutputStream( configFilename );
        // save properties to file, include a header comment 
        this.store(outStrm, "This is the Server configuration file");

        } catch (IOException io) {
            logger.error( "The file :{0} could not be opened", configFilename,io);
        } finally {
            if (outStrm!= null) {
                try {
                    outStrm.close();
                } catch (IOException e) {
                  logger.error("The file :{0} could not be closed", configFilename, e);
                }
            }
        }
    } 
}

我依靠 Properties 父级来启动我使用“this”访问的 Properties。所以现在主要看起来像:

public static void main(String[] args) {

    ClientProperties p = new ClientProperties();
    p.readPropertiesFromFile(); 
    String txt = p.getProperty("xPanelsize");
         System.out.println("Panel size x = " + txt );
    p.setProperty("xPanelsize","64");
    p.writePropertiesToFile();


}

该类现在隐藏了有关读取、写入和文件的所有管理员。至关重要的是,它避免了为每个属性编写一个 setter/getter(我有比这里显示的两个更多的属性)。这就是我在第一个版本中所拥有的。

感谢您的帮助。我自己要花很长时间才能弄清楚这一切。

【讨论】:

    【解决方案2】:

    这是我对你的例子的建议。

    首先,您不需要像这样再次编辑 writePropertiesToFile 方法中的属性:

    public void writePropertiesToFile() {
        // saves the current properties to file. Overwrites the existing properties.
        // Properties props = new Properties(); // a list of properties
        OutputStream outStrm = null;
        logger.info("Writing default flag config properties.");
        logger.debug("Panel size x = " + xPanelSizeStg);
        try {
            outStrm = new FileOutputStream(configFilename);
            // set the properties values
            //props.setProperty("xPanelsize", xPanelSizeStg);
            //props.setProperty("yPanelsize", yPanelSizeStg);
            // save properties to file, include a header comment
            props.store(outStrm, "This is the Server configuration file");
    
        } catch (IOException io) {
            logger.error("The file :{0} could not be opened", configFilename, io);
        } finally {
            if (outStrm != null) {
                try {
                    outStrm.close();
                } catch (IOException e) {
                    logger.error("The file :{0} could not be closed", configFilename, e);
                }
            }
        }
    }
    

    然后,您只需在类中使用全局变量 -props- 创建一个 setProperty 方法。

    private void setProperty(String key, String value) {
       this.props.setProperty(key, value);
    }
    

    如果您的属性文件如下图所示:

    xPanelsize 的值应在运行应用程序后更改。

    public static void main(String[] args) {
        Properties props = null;
        ClientProperties p = new ClientProperties();
        props = p.readPropertiesFromFile();
        String xPanelsize = props.getProperty("xPanelsize");
        System.out.println("Panel size x = " + xPanelsize);
        p.setProperty("xPanelsize", "64"); // method not found error
    
        p.writePropertiesToFile();
    
        props = p.readPropertiesFromFile();
        xPanelsize = props.getProperty("xPanelsize");
        System.out.println("So, now the Panel size x = " + xPanelsize);
    }
    

    调试消息是,

    属性文件内容为:

    这里是完整的来源:

    package stackoverflow;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Properties;
    import java.util.logging.Level;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /* Defines key properties of the iFlag application.
     * Methods read and write properties.
    */
    
    public class ClientProperties {
        Logger logger = LoggerFactory.getLogger(ClientProperties.class.getSimpleName());
        private Properties props;
        private String xPanelSizeStg;
        private String yPanelSizeStg;
        private int xPanelSize;
        private int yPanelSize;
        // private static String configFilename =
        // "/home/myname/config/client_config.properties";
        private static String configFilename = "resource/client_config.properties";
    
        public ClientProperties() {
            props = new Properties();
    
            xPanelSizeStg = "32";
            yPanelSizeStg = "32";
            xPanelSize = 32;
            yPanelSize = 32;
        }
    
        /**
         * Reads properties from file Reads the current properties object from file. The
         * file is stored in /home/mimibox/config/flag_config.properties
         */
    
        public Properties readPropertiesFromFile() {
            // create and load default properties
            InputStream input = null;
            logger.trace("Read flag config properties.");
            try {
                input = new FileInputStream(configFilename);
                // load a properties file from class path, inside static method
                props.load(input);
                // get the property values and save
                xPanelSizeStg = props.getProperty("xPanelsize", "32");
                yPanelSizeStg = props.getProperty("yPanelsize", "32");
            } catch (IOException ex) {
                logger.error("Could not open config file" + configFilename, ex);
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        logger.error("Could not close config file" + configFilename, e);
                    }
                }
            }
            return props;
        }
    
        /**
         * Writes properties to file Writes the current properties object to file. The
         * file is stored in /home/mimibox/config/flag_config.properties
         */
    
        public void writePropertiesToFile() {
            // saves the current properties to file. Overwrites the existing properties.
            // Properties props = new Properties(); // a list of properties
            OutputStream outStrm = null;
            logger.info("Writing default flag config properties.");
            logger.debug("Panel size x = " + xPanelSizeStg);
            try {
                outStrm = new FileOutputStream(configFilename);
                // set the properties values
                //props.setProperty("xPanelsize", xPanelSizeStg);
                //props.setProperty("yPanelsize", yPanelSizeStg);
                // save properties to file, include a header comment
                props.store(outStrm, "This is the Server configuration file");
    
            } catch (IOException io) {
                logger.error("The file :{0} could not be opened", configFilename, io);
            } finally {
                if (outStrm != null) {
                    try {
                        outStrm.close();
                    } catch (IOException e) {
                        logger.error("The file :{0} could not be closed", configFilename, e);
                    }
                }
            }
        }
    
        private void setProperty(String key, String value) {
            this.props.setProperty(key, value);
        }
    
        public int getxPanelSize() {
            return this.xPanelSize;
        }
    
        public void setxPanelSize(int xPanelSize) {
            this.xPanelSize = xPanelSize;
        }
    
        public int getyPanelSize() {
            return yPanelSize;
        }
    
        public void setyPanelSize(int yPanelSize) {
            this.yPanelSize = yPanelSize;
        }
    
        public static void main(String[] args) {
            Properties props = null;
            ClientProperties p = new ClientProperties();
            props = p.readPropertiesFromFile();
            String xPanelsize = props.getProperty("xPanelsize");
            System.out.println("Panel size x = " + xPanelsize);
            p.setProperty("xPanelsize", "64"); // method not found error
    
            p.writePropertiesToFile();
    
            props = p.readPropertiesFromFile();
            xPanelsize = props.getProperty("xPanelsize");
            System.out.println("So, now the Panel size x = " + xPanelsize);
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      您可能需要为您的“道具”对象创建一个 getter。

      public Properties getProps()
      {
          return props;
      }
      

      您将能够像这样调用它:

      p.getProps().setProperty("key", "value");
      

      或者,如果您打算让您的 ClientProperties 类成为 Properties 类的子类,那么您将需要使用 'extends' 并且您可以通过使用来调用它

      p.setProperty("key", "value");
      

      在这种情况下,您的类字段中不需要任何 Properties 对象。

      【讨论】:

      • 好的,根据我非常有限的知识,扩展属性听起来是最好的选择。我将尝试进行更改。
      • 我勾选了这个作为答案,因为这给了我编写工作代码所需的信息。为了他人的利益,我在回答中提供了工作代码。
      猜你喜欢
      • 1970-01-01
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 2013-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多