FK~

Moje odkazy

Ostatní odkazy

Close Windows
Nenajdete mě na Facebooku ani Twitteru
Rozpad EU
Jsem členem FSF
There Is No Cloud …just other people's computers.
Sane software manifesto / Manifest příčetného softwaru

Java a rozšířené atributy souborů

vydáno: 22. 1. 2011 19:42, aktualizováno: 26. 12. 2023 13:14

Java ve své sedmé verzi přinese řadu zajímavých vlastností. Jednou z nich je i podpora práce s rozšířenými atributy souborů, což je funkcionalita poskytovaná souborovým systémem, která umožňuje k souborům ukládat metadata. V dnešním článku si povíme obecně o rozšířených atributech a ukážeme jak s nimi snadno pracovat v Javě (díky OpenJDK 7).

Co jsou rozšířené atributy

Rozšířené atributy jsou funkcí souborového systému (např. ext2, ext3, ext4, JFS, ReiserFS, XFS a Btrfs) a umožňují nám k souborům ukládat metadata ve formě klíč-hodnota. Můžeme si tak k souborům přidávat různé popisy, poznámky nebo třeba uvést kódování znaků. A to vše bez ohledu na interní formát daného souboru a jeho možnosti.

Výhoda oproti metadatům uvnitř souborů: formáty jako např. MP3, JPEG a řada dalších umožňují ukládat metadata přímo do souboru (např. název písničky nebo datum vyfocení). Každý formát má ale vlastní způsob zápisu metadat a pro práci s nimi obvykle potřebujeme nějakou speciální knihovnu. Rozšířené atributy oproti tomu přinášejí standardní API pro práci s metadaty, které je nezávislé na konkrétním formátu. Např. název, autora nebo kódování si přečteme vždy stejným způsobem, ať už se jedná o písničku, obrázek nebo třeba textový dokument.

Výhoda oproti metadatům ve zvláštních souborech: metadata můžeme ukládat mimo vlastní soubor, to se používá třeba v případě kontrolního součtu nebo elektronického podpisu. Vždy musíme dávat pozor, abychom přenesli oba (všechny) soubory a nezapomněli je také správně přejmenovat. S rozšířenými atributy se nám to nestane, tam jsou metadata a vlastní soubor nerozlučně spjaty a při přesouvání nebo přejmenování nemusíme nic řešit – metadata se nám neztratí.

Nevýhoda: rozšířené atributy musí být podporované daným souborovým systémem. Když soubory nahrajeme třeba na disketu nebo flashku s nějakým primitivním FS, o metadata bohužel přijdeme. Totéž by se dalo říct o přenosech po síti. Jenže tam je situace spíš opačná – při přenosu souborů po HTTP nebo e-mailem (SMTP a MIME) se např. informace o MIME typu souboru nebo jeho kódování úspěšně přenáší (pomocí hlaviček příslušných protokolů/formátů) a ztratí se často až ve chvíli uložení souboru na disk. Proto je důležité si rozšířené atributy zapnout a používat je.

Abychom rozšířené atributy mohli používat, zkontrolujeme si v souboru /etc/fstab, že tam máme volbu user_xattr, případně ji přidáme (pak je potřeba znovu připojit souborový systém např. pomocí mount -o remount -a).

Nejvíce nás budou asi zajímat uživatelské atributy, ty se nacházejí ve jmenném prostoru user, ale existují i další: system, security nebo trusted.

Pro vyzkoušení rozšířených atributů si nainstalujeme nástroj pro příkazovou řádku: balíček attr. Pomocí příkazů getfattr, setfattr, případně attr můžeme atributy číst a zapisovat.

Rozšířené atributy podporují i programy jako curl nebo wget – pomocí jednoho z příkazů:

curl --xattr --output frantovo.xhtml https://blog.frantovo.cz/ 
wget --xattr -O       frantovo.xhtml https://blog.frantovo.cz/

si stáhneme stránku z webu a curl nám k souboru přidá dva rozšířené atributy:

  • user.xdg.origin.url – URL původního umístění dokumentu
  • user.mime_type – MIME typ a kódování

To je velice užitečné, protože často se stává, že si stáhneme nějaké materiály z webu a pak zapomeneme, odkud to bylo a později pracně hledáme původní zdroj. U kódování bývá podobný problém – zatímco při načítání z webu prohlížeč zjistí kódování z HTTP hlaviček, při načítání z disku tyto hlavičky chybí a prohlížeč musí kódování buď uhádnout, nebo ho hledat uvnitř souboru.

Pro program wget existují minimálně dva patche: jeden napsal Petr Písař a druhý Stefan Tomanek takže i při stahování tímto programem si můžete ukládat rozšířené atributy. Pozn. 2023-12-26: program wget už delší dobu není potřeba patchovat – rozšířené atributy umí ve standardní verzi.

Standardy a doporučení

Abychom se vzájemně domluvili a nepoužíval každý svoje vlastní nekompatibilní názvy atributů, je dobré dodržovat nějaké konvence. Freedesktop.org radí, aby atributy specifické pro konkrétní aplikaci obsahovaly předponu – např.:

user.nějakáMojeAplikace.nějakýAtribut = "hodnota atributu"

Tím se předejde konfliktům v názvech. Pak existují společné atributy používané různými programy:

  • user.mime_type
  • user.charset
  • user.creator

a navržené atributy jako jsou:

  • user.xdg.comment
  • user.xdg.origin.url
  • user.xdg.origin.email.subject
  • user.xdg.language
  • user.xdg.publisher

a další. Kromě toho můžeme autributy pojmenovat podle standardu Dublin Core – např.:

  • user.dublincore.title
  • user.dublincore.creator
  • user.dublincore.rights

Simple Dublin Core Metadata Element Set definuje celkem 15 elementů.

Jak vidíme, možností je spousta. Pro začátek bude dobré ukládat k souborům alespoň jejich MIME typ a kódování znaků.

Práce s rozšířenými atributy v Javě

V současné době se chystá sedmá verze Javy, resp JDK 7, ve které bude spousta zajímavých novinek. Kromě jiného se můžeme těšit i na JSR 203: More new I/O APIs for the Java platform (NIO.2) A nemusíme se jen těšit, můžeme ho rovnou používat – vývojové verze OpenJDK 7 už jsou poměrně dost funkční.

V novém API se setkáváme s abstraktní třídou java.nio.file.Path jejíž instance představují soubor (nemusí nutně existovat). Jedná se o nástupce dříve používaného java.io.File, který všichni dobře známe. Když ve svém programu máme soubor, jednoduše z něj získáme cestu:

File soubor = new File("/cesta/k/souboru.txt");
Path cesta = soubor.toPath();

Nebo si vytvoříme cestu rovnou:

Path cesta = Paths.get("/cesta/k/souboru.txt");

Jakmile máme instanci Path, otevírají se nám možnosti nového API. Protože nás teď zajímají rozšířené atributy, vytvoříme si na ně pohled:

UserDefinedFileAttributeView pohled =
	cesta.getFileAttributeView(UserDefinedFileAttributeView.class);

Protože jsme zvolili UserDefinedFileAttributeView, pracujeme nad uživatelskými atributy (ne systémovými viz výše), tudíž se pohybujeme pořád ve jmenném prostoru user. Při práci s atributy teď tedy nepoužíváme předponu user – o to se postará Java. Z pohledu získáme seznam atributů daného souboru.

List<String> jménaAtributů = pohled.list();

Hodnoty jednotlivých atributů si načteme přes ByteBuffer:

for (String jménoAtributu : jménaAtributů) {
	ByteBuffer hodnotaAtributu = ByteBuffer.allocate(pohled.size(jménoAtributu));
	pohled.read(jménoAtributu, hodnotaAtributu);
	System.out.println(jménoAtributu + " = "  + dekóduj(hodnotaAtributu));
}

Pro převod bajtů na text použijeme následující metodu:

private static String dekóduj(ByteBuffer bajty) {
	bajty.flip();
	/** Freedesktop.org říká, že by to mělo být UTF-8 */
	return StandardCharsets.UTF_8.decode(bajty).toString();
}

Zápis atributu je opět jednoduchý – jen musíme zase převést textovou hodnotu zpátky na bajty:

pohled.write("názevAtributu", zakóduj("hodnota atributu"));

Kompletní funkční příklad najdete ve zdrojových kódech ukázkové aplikace – viz níže.

Toto API využijeme např. když budeme programovat souborové servelety – pak nemusíme MIME typ hádat podle přípony nebo prvních bajtů v souboru a jednoduše si ho přečteme z atributů (za předpokladu, že je tam uložený, samozřejmě). Nebo když budeme vyvíjet nějaký CMS – budeme mít metadata a soubory těsně spjaté a nebudeme muset řešit synchronizaci a referenční integritu mezi databází a souborovým systémem. Rozšířené atributy můžeme využít i k ošetření přístupových práv na úrovni aplikace – např. můžeme soubory označovat podle stupně utajení a aplikace je pak bude poskytovat jen uživatelům s příslušným pověřením. Možnostem využití se meze nekladou a záleží jen na vaší fantazii, co na téhle technologii postavíte.

Ukázková aplikace: rozsirene-atributy

Vytvořil jsem jednoduchou GUI aplikaci, která umožnňuje zobrazovat a měnit rozšířené atributy souborů. Stáhnout si ji můžete z mého mercurialu příkazem:

hg clone https://hg.frantovo.cz/rozsirene-atributy/

a potom přeložit pomocí antu. Jediné, co potřebujete je OpenJDK 7. Aplikace byla vyvinuta a testována s touto verzí:

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b103)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b04, mixed mode)

Program se spouští takto:

rozšířené-atributy.sh "název_souboru.txt"          # původní verze v0.1 z roku 2012
rozšířené-atributy.sh --soubor "název_souboru.txt" #    nová verze v0.2 z roku 2023

Rozšířené atributy – GUI v Javě

Atributy můžete přidávat nebo mazat. Změny se provádějí hned, co ukončíte editaci příslušné buňky v tabulce.

Poznámka: protože se nejedná o žádnou kritickou aplikaci, rozhodl jsem se ji zneužít k jednomu experimentu. Podle Java Language Specification – 3.8 Identifiers se nemusíme omezovat jen na ASCII znaky, proto jsou všechny názvy tříd a metod v tomto programu psané česky a to včetně háčků a čárek.

„Letters and digits may be drawn from the entire Unicode character set, which supports most writing scripts in use in the world today, including the large sets for Chinese, Japanese, and Korean. This allows programmers to use identifiers in their programs that are written in their native languages.“

A vypadá to, že to skutečně funguje. Jestli chcete pomoci, otestujte program na své platformě a dejte vědět, jak to šlo.

Závěr

Dnešní článek měl dva cíle – jednak udělat osvětu rozšířeným atributům a jednak ukázat, jak snadno se s nimi pracuje (nebo bude pracovat) v nové verzi Javy. Odkazovaná GUI aplikace je svobodný software pod GNU GPL licencí. Je myšlena primárně jen jako ukázka nového API, ale třeba někomu bude k užitku. Zmínili jsme i standard pro metadata Dublin Core, který se vám může hodit nezávisle na souborových atributech – můžete ho využít třeba v XHTML.

Aktualizace 2023-12-26

Tenhle program sice vznikl spíše jako experiment a ukázka nových možností Javy 7, ale nakonec jsem ho vlastně celé ty roky spokojeně používal pro občasné editace a prohlížení rozšířených atributů souborů. A až letos se objevila potřeba v programu něco měnit. Seznam vylepšení:

  • Možnost sestavit program pomocí nástrojů Make, Ant i Maven: Všechny tři skripty jsou ručně psané a maximálně jednoduché. Použít můžete kterýkoli z nich, takže pokud např. máte Make, stačí vám JDK a nemusíte si instalovat ani Ant ani Maven. Všechny tři způsoby jsou rovnocenné a na sobě nezávislé (není to tak, že by Make volal Maven nebo Maven volal Ant, což nemám rád - tyhle řetězení a kombinace podobných nástrojů vedou obvykle na dost nepřehlednou spleť).
  • Tlačítko pro kopírování atributů do schránky: Exportuje názvy a hodnoty všech atributů ve formátu CSV. Výsledkem jsou strojově čitelná data, která můžeme vložit např. do LibreOffice, Office pipe nebo třeba na vstup programu relpipe-in-csv.
  • Parametry na příkazové řádce: Už to není jen název souboru, ale i další volby. Parametry lze zadávat česky i anglicky. Je tedy potřeba zadat alespoň --file ... nebo --soubor ... (toto je zpětně nekompatibilní změna).
  • Možnost definovat slovník atributů: V původní verzi byla napevno daná sada názvů atributů, které program napovídal (kromě toho šlo samozřejmě zadávat i vlastní). Nově lze pomocí parametrů na příkazové řádce definovat vlastní atributy a jejich hodnoty – ty se pak v programu nabízejí. Můžeme si tedy připravit specifické spouštěcí skripty, které nám naparametrizují program tak, aby nabízel atributy a hodnoty pro nějakou aplikaci – nebo nějakou naši univerzální sadu všech používaných atributů.
  • Volitelné zamykání souboru: Program lze spustit v režimu, kdy před editací soubor otevře pro zápis a zamkne a po editaci uvolní zámek a zavře. Do samotného souboru sice nezapisujeme, ale slouží to k signalizaci změn spolupracujícím procesům - ty můžou soubor taky zamykat a hlavně můžou soubor sledovat přes inotify a čekat na událost CLOSE_WRITE a reagovat na naše změny. Výhoda je v tom, že můžeme atomicky „odeslat“ celou sadu změn (několik atributů) a druhý program ví, že už má začít číst (tzn. nebude číst, když my ještě zapisujeme). Je samozřejmě žádoucí, aby oba procesy používaly zámky (stejného typu), nicméně i když druhý proces soubor nezamyká a jen reaguje na událost, bude to fungovat, protože se dá předpokládat, že uživatel v GUI nenakliká další změny rychleji, než druhý proces stihne načíst ty předchozí.

Původní verze z roku 2012 je označená jako v0.1. Novou verzi z roku 2023 jsem označil jako v0.2. Program je lokalizovaný do češtiny a angličtiny a výběr jazyka se řídí standardní proměnnou prostředí $LANG.

Rozšířené atributy – GUI v Javě – verze v0.2 z roku 2023 s exportem do CSV

Příklad parametrizace pro potřeby konkrétního programu – zamyká soubor a nabízí požadované atributy a jejich hodnoty:

#!/bin/bash

JAVA_BIN="java";
SWING_LAF="-Dswing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel";
# SWING_LAF="-Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
# SWING_LAF="-Dswing.defaultlaf=com.sun.java.swing.plaf.motif.MotifLookAndFeel";
JAR="$HOME/.../target/rozsirene-atributy-0.2-SNAPSHOT.jar";

config=(
	--locking-mode            "mandatory"
	--attribute-definition    "shader-shark.texture.mag-filter"        ""
		--value               "linear"                                 ""
		--value               "nearest"                                ""
	--attribute-definition    "shader-shark.texture.min-filter"        ""
		--value               "linear"                                 ""
		--value               "nearest"                                ""
);

export LANG=en_US.UTF-8

${JAVA_BIN} ${SWING_LAF} -jar ${JAR} "${config[@]}" "${@}";

(viz program ShaderShark)

Témata: [Java]

Komentáře čtenářů

Tento článek zatím nikdo nekomentoval

Přidat komentář

reagujete na jiný komentář (zrušit)
jméno nebo přezdívka
název příspěvku
webová stránka, blog
e-mailová adresa
nápověda: možnosti formátování
ochrana proti spamu a špatným trollům

Náhled komentáře