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:

  1. Hitta Class eller ClassLoader som hittar resursen.
  2. Hitta resursen.
  3. Få byte-strömmen för resursen.
  4. Läsa och bearbeta byte-strömmen.
  5. 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 dig Class objektet för String typen.

  • Den Object.getClass() kommer att ge dig Class objekt för den typ od något föremål; t.ex. "hello".getClass() är ett annat sätt att få Class av String .

  • Class.forName(String) kommer (om nödvändigt) att ladda en klass dynamiskt och returnera sitt Class 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 och Class 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 med URL.toStream() . De kan vara file: URL: er eller andra konventionella URL: er, men om resursen finns i en JAR-fil kommer de att vara jar: URL: er som identifierar JAR-filen och en specifik resurs i den.

  • Om din kod använder en getResourceAsStream metod (eller URL.toStream() ) för att få en InputStream , är den ansvarig för att stänga strömobjektet. Underlåtenhet att stänga strömmen kan leda till en resursläcka.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow