Properties - pliki tekstowe
Koziołek
1 Wstęp
2 Pliki .properties
3 Ładowanie plików .properties
4 Zapisywanie do plików .properties
5 Podsumowanie
Wstęp
Zapewne każdy z was spotkał się z tym problemem. Problemem, który dręczył pokolenia informatyków i zapewne będzie dręczył kolejne. Gdzie należy trzymać konfigurację potrzebną do prawidłowego działania programu.
Pierwszym i najbardziej naturalnym postępowaniem jest "zaszycie" konfiguracji w kodzie. Jest to najgorsza z możliwych metod. Do jej głównych wad należą:
- trudność wprowadzania zmian. Zmiana wymaga ponownej kompilacji kodu
- możliwa redundancja kodu
Jednak ma ona jedną zaletę. Jest bardzo szybka na etapie implementacji oraz bardzo bezpieczna. Zazwyczaj używa się jej tam gdzie: - nie ma obsługi plików
- są bardzo duże ograniczenia w zakresie wykorzystania pamięci / szybkości procesora
Drugą znacznie bardziej poprawną metodą jest przeniesienie konfiguracji do osobnego pliku. W ten sposób uzyskujemy bardzo dużą elastyczność i możliwość zmiany ustawień bez potrzeby ingerencji w kod. W języku Java istnieją dwie główne metody tworzenia konfiguracji za pomocą plików. Pierwsza z nich to wykorzystanie dokumentów XML. Druga, i tą się tu zajmiemy dokładnie, to wykorzystanie obiektu <font name="Courier New" size="2">Properties</span>.
Pliki .properties
Podstawą działania obiektu Properties są pliki tekstowe. Zgodnie z konwencją mają one rozszerzenie <font name="Courier New" size="2">.properties</span>. Ich zawartość to pary << klucz >>=<< wartość >> każda para w osobnej i pojedynczej linii. Ostatnie oznacza iż wartość nie zależnie jak długa musi znajdować się w jednej linii. Przykład pliku:
# komentarz
klucz=wartość
Istotną cechy to
- plik powinien być zapisany w ISO-8859-1
- należy unikać polskich znaków w nazwach kluczy
- klucze muszą być unikalne
Jak widać kodowanie powoduje że nie będziemy mogli w prosty sposób używać polskich znaków. Rozwiązaniem jest zamiana polskich znaków na kody UTF-8:
- Ą - \u0104; ą - \u0105
- Ć - \u0106; ć - \u0107
- Ę - \u0118; ę - \u0119
- Ł - \u0141; ł - \u0142
- Ń - \u0143; ń - \u0144
- Ó - \u00d3; ó - \u00f3
- Ś - \u015a; ś - \u015b
- Ź - \u0179; ź - \u017a
- Ż - \u017b; ż - \u017c
Ładowanie plików .properties
Jak mamy już utworzony nasz plik .properties to czas załadować go do obiektu. W tym celu musimy:
- utworzyć strumień wejściowy <font name="Courier New" size="2">InputStream</span>
- utworzyć obiekt <font name="Courier New" size="2">Properties</span>
- załadować dane ze strumienia wejścia do obiektu <font name="Courier New" size="2">Properties</span>
Dodatkowo wypiszemy jego zawartość.
I oto klasa to realizująca:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesTest {
//Plik z konfiguracją
private File f = new File("conf.properties");
//przyszły obiekt Properties
private Properties properties = new Properties();
public static void main(String[] args) {
System.setProperty("file.encoding", "UTF-8");
PropertiesTest pt = new PropertiesTest();
pt.loadProperties();
System.out.println(pt.properties.getProperty("klucz"));
}
public void loadProperties(){
//Strumień wejściowy
InputStream is;
try {
is = new FileInputStream(f);
//ładujemy nasze ustawienia
properties.load(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Jak widać jest to bardzo proste.
Zapisywanie do plików .properties
Została jeszcze jedna kwestia do poruszenia. Jak zapisywać zmienione ustawienia do plików? Obiekt <font name="Courier New" size="2">Properties</span> posiada dwie metody, które pozwalają na tą operację.
- <font name="Courier New" size="2">save(FileOutputStream, String)</span> - oznaczoną jako przestarzała
- <font name="Courier New" size="2">store(FileOutputStream, String)</span> - zalecaną
Pierwszy argument to strumień wyjścia do którego zostaną zapisane dane. Drugi to komentarz. Tu istotna uwaga jeżeli podamy komentarz jako pusty to zostanie do pliku wstawiona data utworzenia i pusta linia. Jeżeli komentarz będzie równy null to wstawiona zostanie tylko data utworzenia.
Na koniec dodatkowa metoda zapisująca nasze ustawienia:
public void saveProperties(String key, String value){
OutputStream os;
try {
os = new FileOutputStream(f);
properties.setProperty(key, value);
properties.store(os, null);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Podsumowanie
Pliki .properties są podstawowym sposobem zapisu danych konfiguracyjnych. Ich istotną wadą jest konieczność stosowania kodowania ISO-8859-1 co utrudnia stosowanie polskich znaków.
@Olamagato, mówisz o zupełnie innym mechanizmie i zupełnie innym API. Zgadzam się, ze nowszym, ale Properties API nadal jest szeroko używane.
Artykuł w całości zdezaktualizowany przez istniejącą od Javy 1.4 klasę java.util.prefs.Preferences, która właśnie służy do niezależnego od platformy i języka trzymania swoich ustawień. Ustawienia można przechowywać w danych prywatnych konta użytkownika lub w danych systemowych (dla wszystkich kont wspólnie). Rozwiązuje to więc całkowicie problem z kodowaniem polskich znaków. Jedynym ograniczeniem jest limit 8 KB danych, który jak na dane konfiguracyjne jest spory.
Wyrzucone zostanie wtedy FNFE, które zostanie wyłapane przez catch(IOE...) a printStackTrace wypisze nam przyczynę (brak dostępu). Sprawdziłem ;-)
Niekoniecznie. Jeżeli plik istnieje, a nie masz praw do jego odczytu to IOE nie powie ci tego, a FNFE już tak.
Świetny artykuł! Tylko jedna uwaga - w tym przypadku (skoro nie obsługujemy błędów) nie jest niezbędne wyłapywanie wyjątków FileNotFoundException, wystarczy IOException. Pozdrawiam.