Java Language
Resurser (på klassväg)
Sök…
Introduktion
Java tillåter hämtning av filbaserade resurser lagrade inuti en JAR tillsammans med sammanställda klasser. Det här ämnet fokuserar på att ladda dessa resurser och göra dem tillgängliga för din kod.
Anmärkningar
En resurs är filliknande data med ett sökvägsliknande namn, som finns i klassvägen. Den vanligaste resursanvändningen är att binda applikationsbilder, ljud och skrivskyddad data (som standardkonfiguration).
Resurser kan nås med metoderna ClassLoader.getResource och ClassLoader.getResourceAsStream . Det vanligaste fallet är att ha resurser placerade i samma paket som klassen som läser dem; metoderna Class.getResource och Class.getResourceAsStream tjänar detta fall för vanligt bruk.
Den enda skillnaden mellan en getResource-metod och getResourceAsStream-metoden är att den förstnämnda returnerar en URL, medan den senare öppnar den URL och returnerar en InputStream.
Metoderna för ClassLoader accepterar ett sökvägsliknande resursnamn som ett argument och söker på varje plats i ClassLoaders klassväg efter en post som matchar det namnet.
- Om en klassvägsplats är en .jar-fil, betraktas en burkpost med det angivna namnet som en matchning.
- Om en klassvägsplats är en katalog, betraktas en relativ fil under den katalogen med det angivna namnet som en matchning.
Resursnamnet liknar sökvägsdelen i en relativ URL. På alla plattformar använder det framåt snedstreck ( /
) som katalogseparatorer. Det får inte börja med en snedstreck.
Motsvarande metoder för klass är liknande, förutom:
- Resursnamnet kan börja med en snedstreck, i vilket fall den första snedstrecken tas bort och resten av namnet överförs till motsvarande metod i ClassLoader.
- Om resursnamnet inte börjar med en snedstreck, behandlas det som relativt den klass vars getResource- eller getResourceAsStream-metod kallas. Det verkliga resursnamnet blir paket / namn , där paketet är namnet på det paket som klassen tillhör, med varje period ersatt av en snedstreck, och namnet är det ursprungliga argumentet som ges till metoden.
Till exempel:
package com.example;
public class ExampleApplication {
public void readImage()
throws IOException {
URL imageURL = ExampleApplication.class.getResource("icon.png");
// The above statement is identical to:
// ClassLoader loader = ExampleApplication.class.getClassLoader();
// URL imageURL = loader.getResource("com/example/icon.png");
Image image = ImageIO.read(imageURL);
}
}
Resurser bör placeras i namngivna paket, snarare än i roten till en .jar-fil, av samma anledning klasser placeras i paket: För att förhindra kollisioner mellan flera leverantörer. Om till exempel flera .jar-filer finns i klassvägen, och mer än en av dem innehåller en config.properties
post i dess rot, kommer samtal till getResource eller getResourceAsStream-metoderna att returnera config.properties från vilken .jar som listas först i klassvägen. Detta är inte förutsägbart beteende i miljöer där klassvägsordningen inte är under direkt kontroll av applikationen, till exempel Java EE.
Alla getResource- och getResourceAsStream-metoder returnerar null
om den angivna resursen inte finns. Eftersom resurser måste läggas till applikationen vid byggtid bör deras platser vara kända när koden skrivs. ett misslyckande med att hitta en resurs under körning är oftast resultatet av programmeringsfel.
Resurser är skrivskyddad. Det finns inget sätt att skriva till en resurs. Nybörjare utvecklar ofta misstaget att anta att eftersom resursen är en separat fysisk fil när de utvecklas i en IDE (som Eclipse), kommer det att vara säkert att behandla den som en separat fysisk fil i allmänhet. Detta är dock inte korrekt; applikationer distribueras nästan alltid som arkiv som .jar- eller .war-filer, och i sådana fall är en resurs inte en separat fil och kommer inte att vara skrivbar. (GetFile-metoden i URL-klassen är inte en lösning för detta. Trots dess namn returnerar den bara sökvägsdelen för en URL, som inte alls garanteras att vara ett giltigt filnamn.)
Det finns inget säkert sätt att lista resurser vid körning. Återigen, eftersom utvecklarna är ansvariga för att lägga till resursfiler till applikationen vid byggtid bör utvecklarna redan veta sina vägar. Det finns lösningar men de är inte tillförlitliga och kommer så småningom att misslyckas.
Laddar en bild från en resurs
Så här laddar du en medföljande bild:
package com.example;
public class ExampleApplication {
private Image getIcon() throws IOException {
URL imageURL = ExampleApplication.class.getResource("icon.png");
return ImageIO.read(imageURL);
}
}
Laddar standardkonfiguration
Så här läser du standardkonfigurationsegenskaper:
package com.example;
public class ExampleApplication {
private Properties getDefaults() throws IOException {
Properties defaults = new Properties();
try (InputStream defaultsStream =
ExampleApplication.class.getResourceAsStream("config.properties")) {
defaults.load(defaultsStream);
}
return defaults;
}
}
Laddar resurs med samma namn från flera JAR
Resurs med samma sökväg och namn kan finnas i mer än en JAR-fil på klassvägen. Vanliga fall är resurser som följer en konvention eller som ingår i en förpackningsspecifikation. Exempel på sådana resurser är
- META-INF / MANIFEST.MF
- META-INF / beans.xml (CDI Spec)
- ServiceLoader-egenskaper som innehåller implementeringsleverantörer
För att få tillgång till alla dessa resurser i olika burkar måste man använda en ClassLoader, som har en metod för detta. Den returnerade Enumeration
kan enkelt konverteras till en List
hjälp av en samlingsfunktion.
Enumeration<URL> resEnum = MyClass.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
ArrayList<URL> resources = Collections.list(resEnum);
Hitta och läsa resurser med hjälp av en klasslastare
Resursbelastning i Java består av följande steg:
- Hitta
Class
ellerClassLoader
som hittar resursen. - Hitta resursen.
- Få byte-strömmen för resursen.
- Läsa och bearbeta byte-strömmen.
- Stänger byte-strömmen.
De tre sista stegen utförs vanligtvis genom att skicka URL till en biblioteksmetod eller konstruktör för att ladda resursen. Du kommer vanligtvis att använda en getResource
metod i det här fallet. Det är också möjligt att läsa resursdata i applikationskod. Du kommer vanligtvis att använda getResourceAsStream
i det här fallet.
Absoluta och relativa resursvägar
Resurser som kan laddas från klassvägen betecknas med en sökväg . Banans syntax liknar en UNIX / Linux-filväg. Det består av enkla namn separerade med framåt snedstreck ( /
) -tecken. En relativ sökväg börjar med ett namn, och en absolut sökväg börjar med en separator.
Som Classpath-exemplen beskriver definierar en JVM: s klassväg ett namnutrymme genom att lägga över namnområdena på katalogerna och JAR- eller ZIP-filer i klassvägen. När en absolut sökväg löses tolkar det klasslastarna det initiala /
som betyder roten till namnområdet. Däremot kan en relativ sökväg lösas i förhållande till någon "mappen" i namnområdet. Mappen som används beror på objektet du använder för att lösa sökvägen.
Skaffa en klass eller klasslastare
En resurs kan lokaliseras med användning av antingen en Class
föremål eller en ClassLoader
-objekt. En Class
objekt kan lösa relativa sökvägar, så du kommer vanligtvis att använda en av dessa om du har en (klass) i förhållande resurs. Det finns en mängd olika sätt att få en Class
objekt. Till exempel:
En klass bokstavlig ger dig
Class
objekt för varje klass som du kan namnge i Java källkoden; t.ex.String.class
ger digClass
objektet förString
typen.Den
Object.getClass()
kommer att ge digClass
objekt för den typ od något föremål; t.ex."hello".getClass()
är ett annat sätt att fåClass
avString
.Class.forName(String)
kommer (om nödvändigt) att ladda en klass dynamiskt och returnera sittClass
objekt; t.ex.Class.forName("java.lang.String")
.
Ett ClassLoader
objekt erhålls vanligtvis genom att ringa getClassLoader()
på ett Class
objekt. Det är också möjligt att få tag på JVM: s standardklasslastare med hjälp av ClassLoader.getSystemClassLoader()
statisk ClassLoader.getSystemClassLoader()
.
get
metoderna
När du har en Class
eller ClassLoader
instans kan du hitta en resurs med någon av följande metoder:
metoder | Beskrivning |
---|---|
ClassLoader.getResource(path) ClassLoader.getResources(path) | Returnerar en URL som representerar resursens plats med den givna sökvägen. |
ClassLoader.getResources(path) Class.getResources(path) | Returnerar en Enumeration<URL> ger URL: erna som kan användas för att hitta foo.bar resursen; se nedan. |
ClassLoader.getResourceAsStream(path) Class.getResourceStream(path) | Returnerar en InputStream från vilken du kan läsa innehållet i foo.bar resursen som en sekvens av byte. |
Anmärkningar:
Den största skillnaden mellan
ClassLoader
ochClass
versionerna av metoderna är på det sätt som relativa vägar tolkas.-
Class
löser en relativ sökväg i "mappen" som motsvarar klasserpaketet. -
ClassLoader
metoderna behandlar relativa vägar som om de var absoluta; dvs lösa dem i "rotmappen" i klassvägsnamnområdet.
-
Om den begärda resursen (eller resurserna) inte kan hittas
getResource
och getResourceAsStream-methods return
null, and the
getResources-methods return an empty
uppräkning`.De returnerade URL:
URL.toStream()
kan lösas medURL.toStream()
. De kan varafile:
URL: er eller andra konventionella URL: er, men om resursen finns i en JAR-fil kommer de att varajar:
URL: er som identifierar JAR-filen och en specifik resurs i den.Om din kod använder en
getResourceAsStream
metod (ellerURL.toStream()
) för att få enInputStream
, är den ansvarig för att stänga strömobjektet. Underlåtenhet att stänga strömmen kan leda till en resursläcka.