Every modern Java application relies on configuration management. Whether it's a database connection string, API key, or application logging level, properties files (.properties
) provide a simple yet powerful way to manage settings. These plain text files store data in key=value
format, making them easy to read, modify, and load.
Java provides the Properties
class to handle configuration seamlessly. But properties files are still tied to the broader Java I/O ecosystem: you need to understand streams, readers, writers, and NIO.2 APIs to fully harness them. This tutorial will guide you through reading, writing, and managing properties files, covering best practices, advanced techniques, and real-world applications.
Basics of Java I/O
Streams vs Readers/Writers
- InputStream/OutputStream → Binary data.
- Reader/Writer → Character data.
- Properties class → Works with character streams to manage key-value configs.
Example Properties File (config.properties
)
db.url=jdbc:mysql://localhost:3306/mydb
db.username=admin
db.password=secret
app.mode=production
Reading Properties Files
Using FileInputStream
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ReadPropertiesExample {
public static void main(String[] args) {
Properties props = new Properties();
try (FileInputStream fis = new FileInputStream("config.properties")) {
props.load(fis);
System.out.println("DB URL: " + props.getProperty("db.url"));
System.out.println("Mode: " + props.getProperty("app.mode"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using FileReader
import java.io.FileReader;
import java.util.Properties;
public class ReadPropertiesReaderExample {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
try (FileReader reader = new FileReader("config.properties")) {
props.load(reader);
System.out.println("Username: " + props.getProperty("db.username"));
}
}
}
Writing and Updating Properties Files
Example: Updating a Property
import java.io.FileOutputStream;
import java.util.Properties;
public class WritePropertiesExample {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.setProperty("db.url", "jdbc:mysql://localhost:3306/mydb");
props.setProperty("db.username", "admin");
props.setProperty("db.password", "newPassword123");
try (FileOutputStream fos = new FileOutputStream("config.properties")) {
props.store(fos, "Updated Database Config");
}
}
}
Appending or Modifying Properties
Properties props = new Properties();
props.load(new FileInputStream("config.properties"));
props.setProperty("app.mode", "development");
props.store(new FileOutputStream("config.properties"), "Switch to dev mode");
Intermediate Concepts
Buffered I/O and Properties
Properties can be loaded via BufferedReader for efficiency when working with large config files.
RandomAccessFile with Properties
Although not common, RandomAccessFile
can update single entries in massive properties files without rewriting everything.
Serialization
You can serialize Properties
objects, storing them as binary data for quick reloads.
Alternative Config Formats
Properties are often complemented by JSON, YAML, or XML for advanced configurations. Java can read these formats using external libraries.
Advanced I/O with NIO and NIO.2
Using Path and Files
import java.nio.file.*;
import java.util.*;
public class NioPropertiesExample {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
Path path = Paths.get("config.properties");
props.load(Files.newBufferedReader(path));
props.setProperty("feature.toggle", "enabled");
props.store(Files.newBufferedWriter(path), "Feature flag updated");
}
}
Directory Monitoring with WatchService
Automatically reload properties when files change:
WatchService watchService = FileSystems.getDefault().newWatchService();
Path configDir = Paths.get(".");
configDir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
File Locking
Prevent concurrent modification with FileChannel.lock()
.
Performance & Best Practices
- Always close streams using try-with-resources.
- Specify encoding explicitly (ISO-8859-1 default, but UTF-8 preferred).
- Backup configs before modifications.
- Use environment-specific property files (
config-dev.properties
,config-prod.properties
). - For distributed apps, centralize properties in config servers (e.g., Spring Cloud Config).
Framework Case Studies
- Spring Boot: Reads from
application.properties
orapplication.yml
. - Log4j/SLF4J: Reads log configuration from
.properties
files. - Hibernate: Loads DB configs from
hibernate.properties
. - Netty: Reads performance tuning configs.
- Microservices: Externalized configuration through
.properties
or config servers.
Real-World Scenarios
- Database Configuration: Update DB passwords dynamically.
- Feature Flags: Toggle features using property keys.
- Environment Switching: Switch between dev, test, prod modes.
- Centralized Configs: Use properties files across multiple services.
- Secret Management: Rotate keys with minimal file edits.
📌 What's New in Java Versions?
- Java 7+: Introduced NIO.2 (
Path
,Files
,WatchService
). - Java 8: Streams API integrated with Files (
Files.lines()
). - Java 11: Convenience methods (
Files.readString
,Files.writeString
). - Java 17: Performance improvements in file APIs.
- Java 21: Virtual threads improve blocking I/O scalability.
Conclusion & Key Takeaways
Properties files remain the cornerstone of Java configuration management. While the Properties
class makes reading and writing easy, combining it with NIO.2, WatchService, and best practices ensures scalable and secure applications.
Key Takeaways:
- Use the
Properties
class for key-value configs. - Integrate NIO.2 for modern file handling.
- Secure and backup sensitive properties.
- Leverage frameworks like Spring Boot for externalized configs.
FAQ
Q1. What’s the default encoding of properties files?
A: ISO-8859-1, though UTF-8 is recommended.
Q2. How do I update a property without overwriting comments?
A: The Properties.store()
method overwrites comments; for preservation, use custom libraries.
Q3. Can properties files be encrypted?
A: Not directly, but you can store encrypted values and decrypt at runtime.
Q4. What’s the difference between .properties and YAML?
A: .properties
are flat key-value, while YAML supports hierarchical configs.
Q5. Can WatchService reload properties automatically?
A: Yes, by monitoring file changes and reloading configs.
Q6. What happens if a key is missing in Properties?
A: getProperty()
returns null, or you can provide a default value.
Q7. Can I use Properties with XML files?
A: Yes, using loadFromXML()
and storeToXML()
.
Q8. Are properties thread-safe?
A: No, external synchronization is required.
Q9. How do frameworks like Spring Boot manage properties?
A: Through externalized config in application.properties
or YAML.
Q10. Is it better to use Properties or JSON for configs?
A: Properties for simple setups, JSON/YAML for complex hierarchical configs.