Frage

Ich versuche, eine XML-Datei innerhalb einer jar-Datei zuzugreifen, von einem separaten Gefäß, das als Desktop-Anwendung ausgeführt wird. Ich kann die URL in die Datei bekommen ich brauche, aber wenn ich das auf einen Filereader übergeben (als String) Ich erhalte eine FileNotFoundException sagen: „Der Dateiname, Verzeichnisname oder Datenträgerbezeichnung ist falsch.“

Als Bezugspunkt, habe ich keine Probleme beim Lesen Bild Ressourcen aus dem gleichen Glas, vorbei an die URL zu einem ImageIcon Konstruktor. Dies scheint darauf hinzudeuten, dass die Methode, die ich bin mit der URL zu erhalten, ist richtig.

URL url = getClass().getResource("/xxx/xxx/xxx/services.xml");
ServicesLoader jsl = new ServicesLoader( url.toString() );

Innerhalb der ServicesLoader Klasse Ich habe

XMLReader xr = XMLReaderFactory.createXMLReader();
xr.setContentHandler( this );
xr.setErrorHandler( this );
xr.parse( new InputSource( new FileReader( filename )));

Was bei der Verwendung dieser Technik ist falsch die XML-Datei zu lesen?

War es hilfreich?

Lösung 4

Das Problem war, dass ich in dem Aufruf der Parse-Methode von XMLReader einen Schritt zu weit gehen. Die Parse-Methode akzeptiert ein Input, so gibt es keinen Grund, noch einen Filereader zu verwenden. Ändern der letzten Zeile des Codes oben

xr.parse( new InputSource( filename ));

funktioniert gut.

Andere Tipps

Sieht aus wie Sie verwenden java.lang.Class.getResourceAsStream(String) wollen, finden Sie unter

http : //java.sun.com/javase/6/docs/api/java/lang/Class.html#getResourceAsStream (java.lang.String)

Sie müssen nicht sagen, ob dies ein Desktop oder Web-App ist. Ich würde das getResourceAsStream() Verfahren aus einem entsprechenden Classloader verwenden, wenn es sich um eine Desktop oder der Kontext ist, wenn es sich um eine Web-App ist.

Es sieht aus, als ob Sie das URL.toString Ergebnis als Argument für den Konstruktor FileReader verwenden. URL.toString ist ein bisschen gebrochen, und stattdessen sollten Sie in der Regel url.toURI().toString() verwenden. In jedem Fall ist die Zeichenfolge keinen Dateipfad.

Stattdessen sollten Sie entweder:

  • Führen Sie das URL ServicesLoader und lassen Sie es openStream oder ähnlich nennen.
  • Verwenden Sie Class.getResourceAsStream und nur den Strom übergehen, möglicherweise innerhalb eines InputSource. (Denken Sie daran, für NULL-Werte zu überprüfen, wie die API ein bisschen chaotisch ist.)

Ich möchte darauf hinweisen, dass man Fragen, was, wenn die gleichen Ressourcen in mehreren JAR-Dateien sind. Angenommen, Sie /org/node/foo.txt lesen mögen, aber nicht von einer Datei, sondern von jedem einzelnen JAR-Datei.

Ich habe schon mehrmals in das gleiche Problem laufen. Ich habe gehofft, in JDK 7, dass jemand ein Classpath-Dateisystem schreiben würde, aber leider noch nicht.

Frühling hat die Ressourcenklasse, die Sie Classpath Ressourcen ganz schön zu laden.

Ich schrieb ein kleines Prototyp dieses sehr Problem des Lesen Ressourcen mehr JAR-Dateien bilden zu lösen. Der Prototyp nicht jede Kante Fall behandeln, aber es funktioniert Griff für Ressourcen in Verzeichnissen suchen, die in den JAR-Dateien sind.

Ich habe für ziemlich einmal Stack-Überlauf verwendet. Dies ist die zweite Antwort, die ich beantworten erinnere eine Frage mich so verzeihen, wenn ich zu lange (es ist meine Natur).

Dies ist ein Prototyp Ressource Leser. Der Prototyp ist frei von robuster Fehlerprüfung.

Ich habe zwei Prototyp-JAR-Dateien, die ich eingerichtet haben.

 <pre>
         <dependency>
              <groupId>invoke</groupId>
              <artifactId>invoke</artifactId>
              <version>1.0-SNAPSHOT</version>
          </dependency>

          <dependency>
               <groupId>node</groupId>
               <artifactId>node</artifactId>
               <version>1.0-SNAPSHOT</version>
          </dependency>

Die JAR-Dateien haben jeweils eine Datei unter / org / node / genannt resource.txt.

Dies ist nur ein Prototyp dessen, was ein Handler wie mit Classpath aussehen: // Ich habe auch eine resource.foo.txt in meiner lokalen Ressource für dieses Projekt.

Er nimmt sie alle auf und druckt sie aus.

   

    package com.foo;

    import java.io.File;
    import java.io.FileReader;
    import java.io.InputStreamReader;
    import java.io.Reader;
    import java.net.URI;
    import java.net.URL;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;

    /**
    * Prototype resource reader.
    * This prototype is devoid of error checking.
    *
    *
    * I have two prototype jar files that I have setup.
    * <pre>
    *             <dependency>
    *                  <groupId>invoke</groupId>
    *                  <artifactId>invoke</artifactId>
    *                  <version>1.0-SNAPSHOT</version>
    *              </dependency>
    *
    *              <dependency>
    *                   <groupId>node</groupId>
    *                   <artifactId>node</artifactId>
    *                   <version>1.0-SNAPSHOT</version>
    *              </dependency>
    * </pre>
    * The jar files each have a file under /org/node/ called resource.txt.
    * <br />
    * This is just a prototype of what a handler would look like with classpath://
    * I also have a resource.foo.txt in my local resources for this project.
    * <br />
    */
    public class ClasspathReader {

        public static void main(String[] args) throws Exception {

            /* This project includes two jar files that each have a resource located
               in /org/node/ called resource.txt.
             */


            /* 
              Name space is just a device I am using to see if a file in a dir
              starts with a name space. Think of namespace like a file extension 
              but it is the start of the file not the end.
            */
            String namespace = "resource";

            //someResource is classpath.
            String someResource = args.length > 0 ? args[0] :
                    //"classpath:///org/node/resource.txt";   It works with files
                    "classpath:///org/node/";                 //It also works with directories

            URI someResourceURI = URI.create(someResource);

            System.out.println("URI of resource = " + someResourceURI);

            someResource = someResourceURI.getPath();

            System.out.println("PATH of resource =" + someResource);

            boolean isDir = !someResource.endsWith(".txt");


            /** Classpath resource can never really start with a starting slash.
             * Logically they do, but in reality you have to strip it.
             * This is a known behavior of classpath resources.
             * It works with a slash unless the resource is in a jar file.
             * Bottom line, by stripping it, it always works.
             */
            if (someResource.startsWith("/")) {
                someResource = someResource.substring(1);
            }

              /* Use the ClassLoader to lookup all resources that have this name.
                 Look for all resources that match the location we are looking for. */
            Enumeration resources = null;

            /* Check the context classloader first. Always use this if available. */
            try {
                resources = 
                    Thread.currentThread().getContextClassLoader().getResources(someResource);
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            if (resources == null || !resources.hasMoreElements()) {
                resources = ClasspathReader.class.getClassLoader().getResources(someResource);
            }

            //Now iterate over the URLs of the resources from the classpath
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();


                /* if the resource is a file, it just means that we can use normal mechanism
                    to scan the directory.
                */
                if (resource.getProtocol().equals("file")) {
                    //if it is a file then we can handle it the normal way.
                    handleFile(resource, namespace);
                    continue;
                }

                System.out.println("Resource " + resource);

               /*

                 Split up the string that looks like this:
                 jar:file:/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar!/org/node/
                 into
                    this /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar
                 and this
                     /org/node/
                */
                String[] split = resource.toString().split(":");
                String[] split2 = split[2].split("!");
                String zipFileName = split2[0];
                String sresource = split2[1];

                System.out.printf("After split zip file name = %s," +
                        " \nresource in zip %s \n", zipFileName, sresource);


                /* Open up the zip file. */
                ZipFile zipFile = new ZipFile(zipFileName);


                /*  Iterate through the entries.  */
                Enumeration entries = zipFile.entries();

                while (entries.hasMoreElements()) {
                    ZipEntry entry = entries.nextElement();
                    /* If it is a directory, then skip it. */
                    if (entry.isDirectory()) {
                        continue;
                    }

                    String entryName = entry.getName();
                    System.out.printf("zip entry name %s \n", entryName);

                    /* If it does not start with our someResource String
                       then it is not our resource so continue.
                    */
                    if (!entryName.startsWith(someResource)) {
                        continue;
                    }


                    /* the fileName part from the entry name.
                     * where /foo/bar/foo/bee/bar.txt, bar.txt is the file
                     */
                    String fileName = entryName.substring(entryName.lastIndexOf("/") + 1);
                    System.out.printf("fileName %s \n", fileName);

                    /* See if the file starts with our namespace and ends with our extension.        
                     */
                    if (fileName.startsWith(namespace) && fileName.endsWith(".txt")) {


                        /* If you found the file, print out 
                           the contents fo the file to System.out.*/
                        try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
                            StringBuilder builder = new StringBuilder();
                            int ch = 0;
                            while ((ch = reader.read()) != -1) {
                                builder.append((char) ch);

                            }
                            System.out.printf("zip fileName = %s\n\n####\n contents of file %s\n###\n", entryName, builder);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }

                    //use the entry to see if it's the file '1.txt'
                    //Read from the byte using file.getInputStream(entry)
                }

            }


        }

        /**
         * The file was on the file system not a zip file,
         * this is here for completeness for this example.
         * otherwise.
         *
         * @param resource
         * @param namespace
         * @throws Exception
         */
        private static void handleFile(URL resource, String namespace) throws Exception {
            System.out.println("Handle this resource as a file " + resource);
            URI uri = resource.toURI();
            File file = new File(uri.getPath());


            if (file.isDirectory()) {
                for (File childFile : file.listFiles()) {
                    if (childFile.isDirectory()) {
                        continue;
                    }
                    String fileName = childFile.getName();
                    if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {

                        try (FileReader reader = new FileReader(childFile)) {
                            StringBuilder builder = new StringBuilder();
                            int ch = 0;
                            while ((ch = reader.read()) != -1) {
                                builder.append((char) ch);

                            }
                            System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", childFile, builder);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }

                    }

                }
            } else {
                String fileName = file.getName();
                if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {

                    try (FileReader reader = new FileReader(file)) {
                        StringBuilder builder = new StringBuilder();
                        int ch = 0;
                        while ((ch = reader.read()) != -1) {
                            builder.append((char) ch);

                        }
                        System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", fileName, builder);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

                }

            }
        }

    }


   

Sie können ein vollständigeres Beispiel hier mit der Probe-Ausgabe.

Außerhalb Ihrer Technik, warum nicht den Standard-Java verwenden JarFile Klasse erhalten die Referenzen Sie wollen? Von dort sollte die meisten Ihrer Probleme verschwinden.

Wenn Sie Ressourcen ausgiebig nutzen, könnten Sie mit   Commons VFS .

Auch unterstützt:  * Lokale Dateien  * FTP, SFTP  * HTTP und HTTPS  * Temporäre Dateien „normaler FS gesichert)  * Zip, Jar und Teer (unkomprimiert, tgz oder tbz2)  * Gzip und bzip2  * Ressourcen  * Ram - "ramdrive"  * Mime

Es gibt auch JBoss VFS - aber es ist nicht viel dokumentiert <. / p>

Ich habe 2 CSV-Dateien, die ich verwende, um Daten zu lesen. Das Java-Programm wird als eine ausführbare JAR-Datei exportiert. Wenn Sie es exportieren, wird Sie heraus es nicht damit Ihre Ressourcen nicht exportieren.

Ich habe einen Ordner unter Projekt namens Daten in Eclipse. In diesem Ordner i meine CSV-Dateien gespeichert werden.

Wenn ich brauche diese Dateien verweisen ich es so tun ...

private static final String ZIP_FILE_LOCATION_PRIMARY = "free-zipcode-database-Primary.csv";
private static final String ZIP_FILE_LOCATION = "free-zipcode-database.csv";

private static String getFileLocation(){
    String loc = new File("").getAbsolutePath() + File.separatorChar +
        "data" + File.separatorChar;
    if (usePrimaryZipCodesOnly()){              
        loc = loc.concat(ZIP_FILE_LOCATION_PRIMARY);
    } else {
        loc = loc.concat(ZIP_FILE_LOCATION);
    }
    return loc;
}

Wenn Sie dann das Glas an einer Stelle setzen, so kann er über Kommandozeilen-ran, stellen Sie sicher, dass Sie den Datenordner mit den Ressourcen in die gleiche Position wie die JAR-Datei hinzufügen.

Hier ist ein Beispielcode auf, wie eine Datei ordnungsgemäß in einer JAR-Datei zu lesen (in diesem Fall die aktuelle Ausführung JAR-Datei)

Nur ausführbare ändern mit dem Pfad der JAR-Datei, wenn es nicht die aktuellen läuft.

Dann die filePath auf den Pfad ändern der Datei, in der JAR-Datei verwenden möchten. I.E. Wenn Ihre Datei in

  

someJar.jar \ img \ test.gif

. Stellen Sie die filePath auf "img \ test.gif"

File executable = new File(BrowserViewControl.class.getProtectionDomain().getCodeSource().getLocation().toURI());
JarFile jar = new JarFile(executable);
InputStream fileInputStreamReader = jar.getInputStream(jar.getJarEntry(filePath));
byte[] bytes = new byte[fileInputStreamReader.available()];

int sizeOrig = fileInputStreamReader.available();
int size = fileInputStreamReader.available();
int offset = 0;
while (size != 0){
    fileInputStreamReader.read(bytes, offset, size);
    offset = sizeOrig - fileInputStreamReader.available();
    size = fileInputStreamReader.available();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top