如何安全地读取 Java 中的属性文件?

     2023-02-26     71

关键词:

【中文标题】如何安全地读取 Java 中的属性文件?【英文标题】:How to safely read the property file in Java? 【发布时间】:2015-03-04 22:55:39 【问题描述】:

我有一个像这样的属性文件 -

emailFrom=hello@abc.com
emailTo=world@abc.com

# can be separated by comma
whichServer=UserServer,GuestServer

maxTestInSec=120
numberOfUsers=1000

现在我正在用 Java 读取这样的属性文件,如果一切设置正确,它就可以工作 -

private static final Properties prop = new Properties();

private static String emailFrom;
private static String emailTo;
private static List<String> whichServer;
private static String maxTestInSec;
private static String numberOfUsers;

public static void main(String[] args) 
    readConfig(args);
   

private void readConfig(String[] args) throws FileNotFoundException, IOException 
    if (!TestUtils.isEmpty(args) && args.length != 0) 
        prop.load(new FileInputStream(args[0]));
     else 
        prop.load(TestTask.class.getClassLoader().getResourceAsStream("config.properties"));
    

    emailFrom = prop.getProperty("emailFrom").trim();
    emailTo = prop.getProperty("emailTo").trim();
    whichServer = Arrays.asList(prop.getProperty("whichServer").trim().split(","));
    maxTestInSec = prop.getProperty("maxTestInSec").trim();
    numberOfUsers = prop.getProperty("numberOfUsers").trim();

问题陈述:-

我需要确保如果缺少任何属性值,那么我想为此使用默认值,如果该属性被注释掉,那么我也想使用默认值,但我会记录警告消息指出该属性丢失或为空,因此使用默认值。我正在尝试涵盖读取文件的所有极端情况-

现在假设,如果我没有在上述文件中为我的任何属性指定值,那么我想为我没有提供的属性使用默认值并记录为警告,指出没有值已为此属性提供,因此使用默认值。例如:假设我没有为emailFrom 字段提供任何值,那么我想使用默认值作为hello@abc.com 和其他类似的东西。所有属性的默认值为:

emailFrom=hello@abc.com

emailTo=world@abc.com

whichServer=UserServer

maxTestInSec=30

numberOfUsers=500

此外,如果任何属性被注释掉,则上述代码将通过 NPE 异常。在那种情况下,我如何也可以使用默认值?

我应该开始为此使用命令行解析器吗?处理这些东西最好、最干净的方法是什么?

我不想有很多 if 块来添加检查然后设置默认值。

【问题讨论】:

【参考方案1】:

从 Java 8 开始,最简单的做法是使用 getOrDefault(),它允许您在获取站点指定默认值。例如:

String email = properties.getOrDefault("emailFrom", "hello@abc.com");

这简洁明了,但确实意味着您需要在访问该属性的任何地方指定默认值。

如果这对您不起作用(即您将多次从属性对象中读取值),您可以使用对默认值的内置支持 - 请注意采用 default 的 constructor Properties 对象。这使您可以构造一个包含默认值的 Properties 对象,然后当您加载用户的属性文件时,如果用户未指定值,它将回退到默认值。

private static final Properties DEFAULTS = new Properties();
static 
  DEFAULTS.setProperty("emailFrom", "hello@abc.com");


public Properties getProperties() 
  Properties props = new Properties(DEFAULTS);
  props.load(...);
  return props;

请注意,这与Map 的构造函数的工作方式不同——默认值保留为单独的映射,只有.getProperty() 也查询默认值; Map 中定义的方法,如 .get() 没有。 Properties 扩展 Hashtable 是一个糟糕的决定,这是众多原因之一,但是我的生活...


这些选项有效,但它们都容易出错,因为 a) Properties 是可变的并且 b) 只有一些公共方法回退到 default 实例。我宁愿从不直接公开Properties 对象,而是使用类型安全的方法创建一个包装类,这些方法公开我的应用程序将关心的值。这需要更多的打字,但使用起来更安全。它看起来像这样:

public class ApplicationSettings 
  private final Properties properties = new Properties();
  public ApplicationSettings() 
    properties.load(...);
  

  public String emailFrom() 
    // simple methods are concise, and encode the default right inline
    return properties.getOrDefault("emailFrom", "hello@abc.com");
  

  public int getMaxTestSeconds() 
    // You can do more complex validation if you want, too
    String value = properties.get("maxTestInSec");
    if (value == null) 
      return 30;
    
    int maxTestSeconds = Integer.parseInt(value);
    if (maxTestSeconds <= 0) 
      // could instead log a warning and return the default if you want
      throw new IllegalStateException(
          "maxTestInSec must be positive - was " + maxTestSeconds);
    
    return maxTestSeconds;
  

如果需要,您还可以公开 setter,在将值添加到 Properties 对象之前类似地验证这些值,尽管默认情况下将所有内容设为只读通常是一个好习惯。

【讨论】:

【参考方案2】:

您可以尝试将属性兑现到静态地图中,并在实际使用之前在该地图上进行处理。

private Map<String, String> rawProps = new HashMap<String, String>;
public static Map<String, String> actualProps = new HashMap<String, String>;

static 
    checkMapForNullAndReport();


private static void checkMapForNullAndReport() 
    // Null logic and Reporting logic
    // Empty rawProps and populate the actualProps

我相信这样的东西对你有用。

【讨论】:

【参考方案3】:

如果一个属性被注释掉,返回值为空,所以只需做一个空检查。

if (prop.getProperty("name")==null)

如果某个值未填充,则在trim操作后检查其是否等于空白。

if (prop.getProperty("name").trim().equals(""))

【讨论】:

感谢您的建议。使用这种方法,如果我的配置文件中有 20 个属性,那么这意味着我需要有 40 个 if 块吗?还有其他干净的方法吗? 您可以使用如下枚举获取所有属性名称。枚举 en = prop.propertyNames(); while (en.hasMoreElements()) System.out.println(en.nextElement()); 并确保所有属性都存在。

如何从java中的配置文件中读取嵌套属性

】如何从java中的配置文件中读取嵌套属性【英文标题】:Howtoreadnestedpropertiesfromconfigurationfileinjava【发布时间】:2018-06-0318:42:08【问题描述】:我想从配置文件中读取Name属性。我希望我的配置文件看起来像这样:config.propertiesPers... 查看详情

如何打开一个文件进行写入以安全地允许其他程序读取?

】如何打开一个文件进行写入以安全地允许其他程序读取?【英文标题】:HowcanIopenafileforwritingthatsafelyallowsotherprogramstoread?【发布时间】:2016-05-0704:13:24【问题描述】:我正在打开一个FileStream并使用以下两个代码sn-ps向其写入行... 查看详情

Java 中的 volatile int 是线程安全的吗?

】Java中的volatileint是线程安全的吗?【英文标题】:IsavolatileintinJavathread-safe?【发布时间】:2011-12-0922:48:07【问题描述】:Java中的volatileint是线程安全的吗?也就是说,它可以在不加锁的情况下安全地读写吗?【问题讨论】:【... 查看详情

如何从 thymeleaf 中的属性文件中读取值

】如何从thymeleaf中的属性文件中读取值【英文标题】:HowtoReadvaluesfromapropertiesfileinthymleaf【发布时间】:2019-08-0723:56:39【问题描述】:有没有办法使用springboot从thymleaf中的属性文件中读取值?例如:-验证消息,从属性文件中加载... 查看详情

如何将属性文件读取到硒中的预期数据

】如何将属性文件读取到硒中的预期数据【英文标题】:Howtoreadpropertyfiletotheexpecteddatainselenium【发布时间】:2018-07-2507:25:55【问题描述】:我已经创建了属性文件,想要读取所有的键和值,需要从预期的数据中进行比较。我创建... 查看详情

如何从 Python 中的文件/流中懒惰地读取多个 JSON 值?

】如何从Python中的文件/流中懒惰地读取多个JSON值?【英文标题】:HowIcanIlazilyreadmultipleJSONvaluesfromafile/streaminPython?【发布时间】:2011-10-1617:00:51【问题描述】:我想从Python中的文件/流中读取多个JSON对象,一次一个。不幸的是json... 查看详情

如何有效地读取 LARGE 文本文件中的行数

】如何有效地读取LARGE文本文件中的行数【英文标题】:HowtoreadthenumberoflinesinaLARGEtextfileeffeciently【发布时间】:2017-09-2012:20:15【问题描述】:我有一个大约750,000行的大型文本文件,每隔几秒就会不断更新,我希望能够实时监控... 查看详情

java示例代码_读取spring项目中的属性文件

java示例代码_读取spring项目中的属性文件 查看详情

如何读取属性文件并使用项目 Gradle 脚本中的值?

】如何读取属性文件并使用项目Gradle脚本中的值?【英文标题】:HowtoreadapropertiesfilesandusethevaluesinprojectGradlescript?【发布时间】:2016-09-0306:01:52【问题描述】:我正在编写一个Gradle脚本,我需要在其中读取local.properties文件并使用... 查看详情

java示例代码_jar文件如何读取外部属性文件

java示例代码_jar文件如何读取外部属性文件 查看详情

csharp安全地读取文件(代码片段)

查看详情

如何从项目目录中读取 javascript 中的属性文件?

】如何从项目目录中读取javascript中的属性文件?【英文标题】:Howtoreadapropertiesfileinjavascriptfromprojectdirectory?【发布时间】:2013-10-1902:37:38【问题描述】:我正在构建一个Chrome打包应用程序。如果配置文件在资源目录中并且在启... 查看详情

如何安全地更改用户的配置文件?

】如何安全地更改用户的配置文件?【英文标题】:Howtosafelychangetheuser\'sconfigfile?【发布时间】:2022-01-1520:04:54【问题描述】:当我需要更改配置文件结构时如何处理?例如,假设我想从这里改变它"device_address":"127.0.0.1:5001"到这... 查看详情

Pentaho 5.3 - 如何读取 PRPT 文件中的属性

】Pentaho5.3-如何读取PRPT文件中的属性【英文标题】:Pentaho5.3-HowtoreadapropertyinPRPTfiles【发布时间】:2015-06-1113:14:06【问题描述】:我需要在属性文件中设置一个值,然后在Pentaho5.3的PRPT中读取这个值。如果我理解它,添加我的属性... 查看详情

如何从 javascript 文件中的属性文件中读取值

】如何从javascript文件中的属性文件中读取值【英文标题】:Howtoreadavaluefrompropertiesfileinajavascriptfile【发布时间】:2019-03-2620:05:45【问题描述】:我有一个服务于angularjs的spring-boot项目。前端和后端代码都在同一个项目中。在我的a... 查看详情

如何在 Java 中读取属性文件? [复制]

】如何在Java中读取属性文件?[复制]【英文标题】:HowtoreadapropertiesfileinJava?[duplicate]【发布时间】:2011-09-0901:28:52【问题描述】:我正在使用servlet对数据库连接详细信息进行硬编码,因此如果进行任何更改,我必须重新编译代... 查看详情

如何从 AWS lambda java 中的类路径加载属性文件

】如何从AWSlambdajava中的类路径加载属性文件【英文标题】:HowtoloadpropertyfilefromclasspathinAWSlambdajava【发布时间】:2016-05-2305:23:48【问题描述】:我已经编写了AWSlambda函数,我想从属性文件和类路径中读取数据库连接详细信息,但... 查看详情

如何使用 PHP 安全地将 JSON 数据写入文件

】如何使用PHP安全地将JSON数据写入文件【英文标题】:HowtosafelywriteJSONdatatofileusingPHP【发布时间】:2011-09-0510:26:13【问题描述】:我有用于编辑图像的HTML表单。所有数据都存储在JSON中。当我更改当前图像时,我想通过PHP脚本将... 查看详情