سؤال

أحاول الوصول إلى ملف XML داخل ملف jar، من جرة منفصلة تعمل كتطبيق سطح مكتب.يمكنني الحصول على عنوان URL للملف الذي أحتاجه، ولكن عندما أمرر ذلك إلى FileReader (كسلسلة) أحصل على FileNotFoundException يقول "اسم الملف، أو اسم الدليل، أو بناء جملة تسمية وحدة التخزين غير صحيح."

كنقطة مرجعية، ليس لدي مشكلة في قراءة موارد الصور من نفس الجرة، وتمرير عنوان URL إلى مُنشئ ImageIcon.يبدو أن هذا يشير إلى أن الطريقة التي أستخدمها للحصول على عنوان URL صحيحة.

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

داخل فئة ServicesLoader لدي

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

ما الخطأ في استخدام هذه التقنية لقراءة ملف XML؟

هل كانت مفيدة؟

المحلول 4

وكانت المشكلة التي كنت ذاهبا خطوة أبعد من اللازم في استدعاء الأسلوب تحليل من XMLReader. طريقة تحليل يقبل InputSource، لذلك لم يكن هناك سبب حتى لاستخدام FileReader. تغيير السطر الأخير من التعليمات البرمجية أعلاه إلى

xr.parse( new InputSource( filename ));

ويعمل على ما يرام.

نصائح أخرى

ويبدو كما لو كنت تريد استخدام java.lang.Class.getResourceAsStream(String)، انظر

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

وأنت لا تقول إذا كان هذا هو سطح المكتب على شبكة الإنترنت أو التطبيق. وأود أن استخدام الأسلوب getResourceAsStream() من ClassLoader المناسب اذا كان سطح المكتب أو سياق لو كان التطبيق على شبكة الإنترنت.

يبدو كما لو كنت تستخدم URL.toString النتيجة كحجة ل FileReader البناء. URL.toString مكسور بعض الشيء، وبدلاً من ذلك يجب عليك استخدامه بشكل عام url.toURI().toString().على أية حال، السلسلة ليست مسار ملف.

بدلاً من ذلك، يجب عليك إما:

  • مرر ال URL ل ServicesLoader والسماح لها بالاتصال openStream أو مشابه.
  • يستخدم Class.getResourceAsStream وقم فقط بتمرير الدفق، ربما داخل InputSource.(تذكر التحقق من القيم الخالية لأن واجهة برمجة التطبيقات (API) فوضوية بعض الشيء.)

وأود أن أشير إلى أن أحد القضايا هو ما إذا كان نفس الموارد في ملفات جرة متعددة. دعونا نقول لكم تريد أن تقرأ /org/node/foo.txt، ولكن ليس من ملف واحد، ولكن من كل ملف جرة.

ولقد واجهت هذه المسألة نفسها عدة مرات من قبل. وكنت آمل في JDK 7 أن شخصا ما سوف إرسال بريد الملفات CLASSPATH، ولكن للأسف ليس بعد.

والربيع لديه الدرجة الموارد التي تتيح لك تحميل موارد CLASSPATH جيد للغاية.

وكتبت القليل من النموذج لحل هذه المشكلة بالذات الموارد القراءة تشكل الملفات جرة متعددة. النموذج لا يعالج كل حالة الحافة، ولكنه تعامل مع البحث عن موارد في الدلائل التي هي في ملفات جرة.

ولقد استخدمت المكدس تجاوز لبعض الوقت. هذا هو الجواب الثاني أن أتذكر ردا على سؤال فاغفر لي إذا ذهبت طويل جدا (فمن طبيعتي).

وهذا هو قارئ الموارد النموذج. النموذج يخلو من قوة التحقق من الخطأ.

ولقد اثنين من الملفات جرة النموذج الذي لدي الإعداد.

 <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>

والملفات جرة لكل واحد من الملف تحت / المنظمة / عقدة / دعا resource.txt.

وهذا مجرد نموذج لما معالج ستبدو مع CLASSPATH: // ولدي أيضا resource.foo.txt في الموارد المحلية بلدي لهذا المشروع.

ويختار كل منهم ما يصل ويطبع بها.

   

    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();
                    }

                }

            }
        }

    }


   

يمكنك أن ترى مثالا أكمل هنا مع إخراج نموذج.

وخارج الأسلوب الخاص بك، لماذا لا تستخدم جافا القياسية <لأ href = "http://java.sun.com/javase/6/docs/api/java/util/jar/JarFile.html" يختلط = " نوفولو noreferrer "> JarFile الطبقة للحصول على المراجع التي تريد؟ من هناك معظم مشاكلك يجب ان تذهب بعيدا.

إذا كنت تستخدم الموارد على نطاق واسع، قد تفكر في استخدام   العموم VFS .

ويدعم أيضا:  * ملفات محلية  * FTP، SFTP  * HTTP و HTTPS  * الملفات المؤقتة "دعمت FS العادية)  * الرمز البريدي، جرة والقطران (غير مضغوط، TGZ أو tbz2)  * غزيب وBZIP2  * مصادر  * كبش - "RAMDRIVE"  * التمثيل الصامت

وهناك أيضا جبوس VFS - ولكنها ليست موثقة بكثير <. / P>

ولقد 2 ملفات CSV التي تستخدم لقراءة البيانات. يتم تصدير برنامج جافا كملف جرة runnable. عند تصديره، ويمكنك معرفة ذلك لا تصدر الموارد الخاصة بك معها.

وأضفت مجلد ضمن بيانات تسمى المشروع في الكسوف. في هذا المجلد ط تخزين ملفات CSV بلدي.

وعندما تحتاج إلى مرجع تلك الملفات أفعل ذلك من هذا القبيل ...

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;
}

وبعد ذلك عندما كنت وضعت الجرة في مكان بحيث يمكن ركض عبر سطر الأوامر، تأكد من أن قمت بإضافة مجلد البيانات مع الموارد في نفس الموقع مثل ملف جرة.

وفيما يلي نموذج التعليمات البرمجية على كيفية قراءة الملف بشكل صحيح داخل ملف جرة (في هذه الحالة، فإن الحالي تنفيذ ملف جرة)

ومجرد تغيير للتنفيذ مع مسار ملف جرة الخاص بك إذا لم يكن التيار تشغيل واحد.

وبعد ذلك تغيير أسم دليل إلى مسار الملف الذي تريد استخدامه داخل ملف جرة. بمعنى آخر. إذا كان الملف الخاص بك هو في

<اقتباس فقرة>   

وsomeJar.jar \ IMG \ test.gif

و. تعيين أسم دليل على "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();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top