Class Properties
Lớp Properties trong Java cung cấp một cách triển khai đặc biệt của Hashtable tập trung vào việc lưu trữ và quản lý các thuộc tính cấu hình, trong đó mỗi khóa (key) và giá trị tương ứng (value) trong danh sách thuộc tính đều là chuỗi (String). Bạn có thể lưu/nạp các thuộc tính theo định dạng dòng đơn giản hoặc định dạng XML.
Đặc điểm nổi bật của Class Properties
Khi làm việc với các file cấu hình hoặc dữ liệu thuộc tính, Properties là một lớp tiện lợi và an toàn mà bạn nên cân nhắc. Lớp này kế thừa từ Hashtable, nhưng được thiết kế chuyên biệt để quản lý các cặp khóa-giá trị dưới dạng chuỗi. Điều này mang lại một số đặc điểm nổi bật, giúp nó trở thành công cụ lý tưởng cho việc đọc và ghi dữ liệu cấu hình. Hãy cùng tìm hiểu những đặc điểm này:
↳ Khóa và giá trị dựa trên chuỗi: Các khóa và giá trị trong đối tượng Properties phải là chuỗi. Các khóa hoặc giá trị không phải chuỗi sẽ gây lỗi khi gọi các phương thức như store hoặc save. Nên sử dụng phương thức setProperty để đảm bảo chỉ thêm các khóa và giá trị dạng chuỗi.
↳ An toàn trong nhiều luồng: Lớp Properties là an toàn trong môi trường nhiều luồng, nghĩa là nhiều luồng có thể sử dụng một đối tượng Properties đồng thời mà không cần đồng bộ hóa thêm.
↳ Cảnh báo về các phương thức đã bị gỡ bỏ: Properties kế thừa từ Hashtable, do đó các phương thức put và putAll vẫn có thể sử dụng được với Properties. Tuy nhiên, việc sử dụng chúng không được khuyến khích vì chúng cho phép nhúng các phần tử có khóa hoặc giá trị không phải chuỗi (String) vào Properties. Thay vào đó, bạn nên sử dụng phương thức setProperty để đảm bảo an toàn kiểu dữ liệu.
↳ Lưu trữ và tải thuộc tính dưới định dạng XML: Các phương thức loadFromXML(InputStream) và storeToXML(OutputStream, String, String) cho phép nạp và lưu các thuộc tính theo định dạng XML đơn giản. Mã hóa mặc định là UTF-8, nhưng bạn có thể chỉ định mã hóa cụ thể nếu cần.
↳ Cấu trúc và mã hóa chính xác với DTD (Document Type Definition): DTD là một tập hợp quy tắc xác định cấu trúc của tài liệu XML. DTD giúp đảm bảo rằng dữ liệu trong tệp XML tuân thủ cấu trúc nhất định và hợp lệ.
↳ Đảm bảo chính xác: Việc sử dụng DTD giúp bảo đảm rằng tệp XML có cấu trúc đúng và mọi phần tử và thuộc tính đều được định nghĩa và sử dụng đúng cách.
Định dạng lưu trữ
Khi làm việc với lớp Properties, việc hiểu cách nó lưu trữ dữ liệu là rất quan trọng. Lớp này sử dụng một định dạng văn bản đơn giản và dễ đọc để biểu diễn các cặp khóa-giá trị, cho phép bạn dễ dàng lưu và tải dữ liệu cấu hình vào một file. Dưới đây là các quy tắc cơ bản về định dạng lưu trữ mà bạn cần biết:
↳ Các thuộc tính được lưu trữ theo định dạng dòng đơn giản, mỗi dòng chứa một cặp khóa-giá trị được phân cách bởi dấu bằng (=).
↳ Bình luận (comment) có thể bắt đầu bằng dấu thăng (#).
↳ Ký tự thoát (\) được sử dụng để biểu diễn các ký tự đặc biệt.
Các phương thức lưu/nạp
Một trong những sức mạnh chính của lớp Properties là khả năng dễ dàng lưu và nạp dữ liệu cấu hình từ các tệp tin. Java cung cấp các phương thức tiện lợi để thực hiện việc này, cho phép bạn đọc các thuộc tính từ một tệp và lưu chúng trở lại mà không cần phải tự mình xử lý từng dòng dữ liệu. Các phương thức này được chia thành hai cặp chính, làm việc với các luồng dữ liệu (stream) hoặc luồng ký tự (character stream) tùy theo nhu cầu của bạn:
↳ Phương thức load(Reader)/store(Writer, String) dùng để nạp và lưu các thuộc tính từ/vào luồng ký tự theo định dạng dòng đơn giản.
↳ Phương thức load(InputStream)/store(OutputStream, String) hoạt động tương tự như cặp load(Reader)/store(Writer, String), chỉ khác ở chỗ luồng đầu vào/đầu ra được mã hóa theo chuẩn ISO 8859-1.
Khai báo Class Properties trong Java
Để sử dụng Class Properties, bạn cần import gói java.util vào đầu file Java của mình.
Cú pháp câu lệnh import:
Cú pháp
import java.util.Properties;
Cú pháp khai báo Class Properties:
Cú pháp
public class Properties
extends Hashtable<Object,Object>
Dưới đây là giải thích chi tiết về cú pháp khai báo này:
↳ public: Lớp Properties có thể được truy cập từ bất kỳ đâu trong chương trình.
↳ class Properties: Khai báo một lớp tên là Properties.
↳ extends Hashtable<Object, Object>: Properties kế thừa tất cả các thuộc tính và phương thức của lớp Hashtable. Điều này có nghĩa là Properties kế thừa các phương thức để thao tác với các cặp khóa-giá trị như put, get, remove, và các phương thức khác từ Hashtable.
Tính đặc thù của Properties:
Mặc dù Properties kế thừa từ Hashtable, nó có thêm các tính năng và quy tắc riêng biệt. Cụ thể:
↳ Chỉ cho phép khóa và giá trị là chuỗi: Properties chỉ cho phép các khóa và giá trị là các chuỗi (String). Tuy nhiên, Hashtable có thể chứa bất kỳ kiểu đối tượng nào.
↳ Hỗ trợ lưu và tải dữ liệu: Properties hỗ trợ lưu trữ và tải dữ liệu từ/đến các định dạng văn bản và XML, trong khi Hashtable không hỗ trợ điều này.
↳ Xử lý các tùy chọn cấu hình: Properties thường được sử dụng để lưu trữ các tùy chọn cấu hình và thuộc tính của ứng dụng.
↳ Lớp Hashtable: Hashtable là một lớp trong Java Collections Framework cung cấp một cách để lưu trữ dữ liệu dưới dạng các cặp khóa-giá trị, tương tự như HashMap, nhưng nó đồng bộ hóa các phương thức của mình, điều này làm cho nó an toàn cho đa luồng nhưng có thể làm giảm hiệu suất so với HashMap.
Các phương thức chính trong lớp Properties
Lớp Properties cung cấp các phương thức để quản lý các cặp khóa-giá trị trong một tập tin thuộc tính. Bạn có thể sử dụng các phương thức này để tải, lưu, tìm kiếm và sửa đổi các thuộc tính. Dưới đây là danh sách tất cả các phương thức của lớp Properties trong Java:
↳ String getProperty(String key): Tìm kiếm thuộc tính có khóa được chỉ định trong danh sách thuộc tính này.
↳ String getProperty(String key, String defaultValue): Tìm kiếm thuộc tính có khóa được chỉ định trong danh sách thuộc tính này.
↳ void list(PrintStream out): In danh sách thuộc tính này ra luồng đầu ra được chỉ định.
↳ void list(PrintWriter out): In danh sách thuộc tính này ra luồng đầu ra được chỉ định.
↳ void load(InputStream inStream): Đọc một danh sách thuộc tính (các cặp khóa và phần tử) từ luồng byte đầu vào.
↳ void load(Reader reader): Đọc một danh sách thuộc tính (các cặp khóa và phần tử) từ luồng ký tự đầu vào ở định dạng đơn giản theo dòng.
↳ void loadFromXML(InputStream in): Tải tất cả các thuộc tính được biểu diễn bởi tài liệu XML trên luồng đầu vào được chỉ định vào bảng thuộc tính này.
↳ Enumeration<?> propertyNames(): Trả về một enumeration của tất cả các khóa trong danh sách thuộc tính này, bao gồm các khóa riêng biệt trong danh sách thuộc tính mặc định nếu chưa tìm thấy khóa cùng tên từ danh sách thuộc tính chính.
↳ void save(OutputStream out, String comments): Lỗi thời. Phương thức này không ném ra IOException nếu xảy ra lỗi I/O trong khi lưu danh sách thuộc tính. Cách được ưu tiên để lưu một danh sách thuộc tính là thông qua phương thức store(OutputStream out, String comments) hoặc storeToXML(OutputStream os, String comment).
↳ Object setProperty(String key, String value): Gọi phương thức put của Hashtable.
↳ void store(OutputStream out, String comments): Ghi danh sách thuộc tính này (các cặp khóa và phần tử) trong bảng Properties này vào luồng đầu ra ở định dạng phù hợp để tải vào một bảng Properties bằng phương thức load(InputStream).
↳ void store(Writer writer, String comments): Ghi danh sách thuộc tính này (các cặp khóa và phần tử) trong bảng Properties này vào luồng ký tự đầu ra ở định dạng phù hợp để sử dụng phương thức load(Reader).
↳ void storeToXML(OutputStream os, String comment): Phát ra một tài liệu XML đại diện cho tất cả các thuộc tính có trong bảng này.
↳ void storeToXML(OutputStream os, String comment, String encoding): Phát ra một tài liệu XML đại diện cho tất cả các thuộc tính có trong bảng này, sử dụng mã hóa được chỉ định.
↳ Set<String> stringPropertyNames(): Trả về một tập hợp các khóa trong danh sách thuộc tính này, trong đó khóa và giá trị tương ứng của nó là chuỗi, bao gồm các khóa riêng biệt trong danh sách thuộc tính mặc định nếu chưa tìm thấy khóa cùng tên từ danh sách thuộc tính chính.
Dưới đây là ví dụ về cách sử dụng lớp Properties trong Java để lấy thông tin từ tệp .properties
Bước 1: Tạo tệp config.properties
Tạo một tệp có tên config.properties với nội dung sau:
Tệp: config.properties
database.url=jdbc:mysql://localhost:3306/mydatabase
database.username=root
database.password=secret
Bước 2: Đọc thông tin từ tệp config.properties
Sử dụng lớp Properties để đọc thông tin từ tệp này trong mã Java.
Ví dụ: Example.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Example {
public static void main(String[] args) {
Properties properties = new Properties();
try (InputStream input = new FileInputStream("config.properties")) {
// Load the properties file
properties.load(input);
// Get properties values
String url = properties.getProperty("database.url");
String username = properties.getProperty("database.username");
String password = properties.getProperty("database.password");
// Display the properties
System.out.println("Đường dẫn cơ sở dữ liệu: " + url);
System.out.println("Tên người dùng: " + username);
System.out.println("Mật khẩu: " + password);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Khi chạy chương trình, nó sẽ đọc và hiển thị các giá trị từ tệp config.properties:
Tên người dùng: root
Mật khẩu: secret
Ví dụ về lớp Properties lấy ra các thuộc tính của hệ thống
Dưới đây là một ví dụ về cách sử dụng lớp Properties để lấy ra các thuộc tính của hệ thống bằng phương thức System.getProperties() trong Java:
Ví dụ: Example.java
import java.util.Properties;
import java.util.Set;
public class Example {
public static void main(String[] args) {
// Lấy tất cả các thuộc tính của hệ thống
Properties systemProperties = System.getProperties();
// Duyệt và in ra tất cả các thuộc tính của hệ thống
Set<String> propertyNames = systemProperties.stringPropertyNames();
for (String propertyName : propertyNames) {
String propertyValue = systemProperties.getProperty(propertyName);
System.out.println(propertyName + ": " + propertyValue);
}
}
}
Khi chạy chương trình, nó sẽ in ra danh sách tất cả các thuộc tính của hệ thống:
sun.cpu.isalist: amd64
sun.jnu.encoding: UTF-8
......
Trong ví dụ minh họa trên, phương thức này trả về một đối tượng Properties chứa tất cả các thuộc tính của hệ thống hiện tại. Các thuộc tính này bao gồm thông tin về hệ điều hành, đường dẫn file, ngôn ngữ, phiên bản Java, v.v.
Ví dụ về lớp Properties để tạo tệp thuộc tính (.properties)
Dưới đây là một ví dụ về cách sử dụng lớp Properties để tạo tệp thuộc tính (.properties) trong Java:
Ví dụ: Example.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class Example {
public static void main(String[] args) {
// Tạo một đối tượng Properties
Properties properties = new Properties();
// Thêm các cặp khóa-giá trị vào đối tượng Properties
properties.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
properties.setProperty("database.username", "root");
properties.setProperty("database.password", "password123");
properties.setProperty("app.version", "1.0.0");
properties.setProperty("app.name", "MyApplication");
// Tạo tệp properties
try (FileOutputStream output = new FileOutputStream("config.properties")) {
// Lưu các thuộc tính vào tệp
properties.store(output, "Cấu hình ứng dụng");
System.out.println("Tệp properties đã được tạo thành công.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Khi chạy chương trình, nó sẽ tạo ra một tệp config.properties trong thư mục hiện tại với nội dung như sau:
#Mon Sep 02 12:16:54 ICT 2024
app.name=MyApplication
app.version=1.0.0
database.password=password123
database.url=jdbc\:mysql\://localhost\:3306/mydb
database.username=root
Các cặp khóa-giá trị này có thể được đọc lại trong các chương trình Java khác để cấu hình ứng dụng một cách linh hoạt.
Như vậy, chúng ta đã tìm hiểu các phương thức chính của lớp Properties. Đây là một công cụ đơn giản nhưng rất hiệu quả để quản lý dữ liệu cấu hình dưới dạng các cặp khóa-giá trị, thường được lưu trữ trong các file .properties. Nắm vững cách sử dụng Properties để tải và lưu dữ liệu sẽ giúp bạn dễ dàng quản lý các thiết lập động cho ứng dụng Java của mình, tách biệt logic code khỏi cấu hình hệ thống.