# Zugriff auf eine Access-Datenbank innerhalb eines jar-Files



## Matze2002 (1. Dez 2009)

Hallo zusammen!

Ich hab eine kleine Anwendung mit Hilfe von Eclipse erstellt. Die dabei anfallenden Daten kann der Benutzer (u.a.) in einer Access-Datenbank speichern. Hierfür liegt der Einfachheit halber im Projektpfad eine leere (Default-) Access-Datenbank, die zunächst in das vom Benutzer gewünschte Arbeitsverzeichnis kopiert und anschließend mit Daten gefüllt werden soll. Innerhalb Eclipse funktionier das alles soweit tadellos. 

Das Problem:
Wenn ich ein jar-file erstelle, wird die Datenbank offenbar nicht mehr gefunden. Es kommt immer eine java.io.FileNotFoundException (Das System kann den angegebenen Pfad nicht finden)
Warum denn!? In Eclipse geht's doch auch!

Hier ist der relevante Code-Ausschnitt:

```
...
File filePath = new File(path, "database.accdb"); //path ist der vom Benutzer ausgewählte Zielpfad für die Datenbank "database"
try {
    if(!filePath.exists()) {
        String sourceFile = new String("startup/database.accdb");
        String targetFile = new String(path+"/database.accdb");
        filePath.createNewFile();
        CopyFile.copyFile(sourceFile, targetFile); //kopieren der Default-Datenbank ins Arbeitsverzeichnis
    }
} 
catch (IOException e) {
    e.printStackTrace();
}
...

weiterer Ausschnitt:
public static void copyFile(String src, String dest) {
    FileInputStream  fis = null;
    FileOutputStream fos = null;
    try {
        fis = new FileInputStream( src );
        fos = new FileOutputStream( dest );
        copy( fis, fos );
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    finally {
        if(fis != null) {
            try {
                fis.close(); 
            } 
            catch(IOException e) {
                 e.printStackTrace();
            }
        }
        if(fos != null) {
            try { 
                fos.close(); 
            } 
            catch(IOException e) {
                e.printStackTrace();			
            }
        }
    }
}
```

Vielen Dank schon vorab für jede Anregung.

Mit freundlichen Grüßen,
Matze2002


----------



## L-ectron-X (1. Dez 2009)

Es ist nicht möglich in eine gerade im Zugriff befindliche Jar-Datei zu schreiben.
Wenn sich deine Access-DB also mit in der Jar-Datei befindet, funktioniert das nicht.

Oder wird die Datei ins Benutzerverzeichnis kopiert und du versuchst dann darauf zuzugreifen?


----------



## Matze2002 (1. Dez 2009)

L-ectron-X hat gesagt.:


> Oder wird die Datei ins Benutzerverzeichnis kopiert und du versuchst dann darauf zuzugreifen?


Ja, genau. Oder besser gesagt, sie SOLL aus dem jar-file ins Benutzerverzeichnis kopiert werden. Aber schon beim Zugriff auf die (in dem jar-file liegende) Datenbank innerhalb des jar-files kommt es zu der FileNotFoundException. (Wie ich darauf zugreife, steht in dem ersten Posting.) Das heißt, der Kopiervorgang der Datenbank ins Benutzerverzeichnis misslingt bereits. Somit komm ich gar nicht mehr dazu, Daten in die Datenbank zu schreiben. Seltsamerweise wird aber die Datenbank bei der Ausführung in Eclipse gefunden und der Kopiervorgang klappt.

Viele Grüße


----------



## maki (1. Dez 2009)

In einem Jar gibt es keine Files, den Fehler machen viele.
Arbeite mit getResourceAsStream bzw. getResource.

Smartly load your properties - JavaWorld


----------



## Matze2002 (1. Dez 2009)

Vielen Dank für die Antworten und den Link. Dass es in einem jar keine files gibt wusste ich bislang noch nicht. 
Ich hab den Code jetzt folgendermaßen abgeändert:


```
Ausschnitt aus Initiator.class:
try {
    if(!filePath.exists()) {
        String sourceFile = new String("startup/database.accdb");
        String targetFile = new String(path+"/database.accdb");
        filePath.createNewFile();
        CopyFile.copyFile(sourceFile, targetFile); //kopieren der Default-Datenbank ins Arbeitsverzeichnis
    }
} 

Methode aus Copy.class:
public static void copyFile(String src, String dest) {
    URL in = Copy.class.getResource(src); 
    FileInputStream  fis = null;
    FileOutputStream fos = null;
    try {
        fis = new FileInputStream( in.toString() );
        fos = new FileOutputStream( dest );
        copy( fis, fos );
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    finally {
        if(fis != null) {
            try {
                fis.close(); 
            } 
            catch(IOException e) {
                 e.printStackTrace();
            }
        }
        if(fos != null) {
            try { 
                fos.close(); 
            } 
            catch(IOException e) {
                e.printStackTrace();            
            }
        }
    }
}
```

Es funktioniert aber immer noch nicht. Jetzt fliegt in Zeile 15 eine NullPointerException. Was mache ich falsch?
Ich hab's auch schon mit ClassLoader.getSystemResourceAsStream versucht (ClassLoader.getResourceAsStream geht ja bei static nicht). Leider auch ohne Erfolg... :-(


----------



## maki (1. Dez 2009)

> Jetzt fliegt in Zeile 15 eine NullPointerException. Was mache ich falsch?


Was ist denn Zeile 15?


----------



## Matze2002 (2. Dez 2009)

Oh, sorry! Ich meine natürlich Zeile 17. Peinlich...
Dort sollte ja die Quell-URL in einen String umgewandelt werden, damit der Dateiinhalt über einen FileInputStream eingelesen und dann mit Hilfe des FileOutputStreams in die Zieldatei geschrieben werden kann. Allerdings liefert

```
Copy.class.getResource(src);
```
 offenbar null zurück, sodass die NullPointerException fliegt und es überhaupt nicht zum Einlesen der Quelldatei (also der zu kopierenden Datenbank) kommt.


----------



## Matze2002 (4. Dez 2009)

Hallo maki,

vielen Dank für den Hinweis mit getResourceAsStream(). Nach längerem Porbieren hat es jetzt (endlich) geklappt! 

Viele Grüße,
Matze2002


P.S.: Für alle, die evtl. auf dasselbe Problem stoßen, ist hier der funktionierende Codeausschnitt:

```
Ausschnitt aus Initiator.class:
try {
    if(!filePath.exists()) {
        InputStream sourceFile = Initiator.class.getResourceAsStream("/startup/database.accdb");
        String targetFile = new String(path+"/database.accdb");
        filePath.createNewFile();
        CopyFile.copyFile(sourceFile, targetFile); //kopieren der Default-Datenbank ins Arbeitsverzeichnis
    }
} 
 
Methode aus Copy.class:
public static void copyFile(InputStream src, String dest) {
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream( dest );
        copy( src, fos );
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    finally {
        if(fis != null) {
            try {
                fis.close(); 
            } 
            catch(IOException e) {
                 e.printStackTrace();
            }
        }
        if(fos != null) {
            try { 
                fos.close(); 
            } 
            catch(IOException e) {
                e.printStackTrace();            
            }
        }
    }
}
```


----------

