从jar文件编译和运行期间读取文件差异

时间:2014-09-14 13:48:54

标签: java file maven-3

我正在尝试编写和读取文件。任何人都可以解释是什么让事情变得不同。

我从属性文件中获取属性,并且我有在我的应用程序中使用的不同文件的路径。

问题是我的应用程序的行为会在运行此代码时发生变化。例如,如果我通过maven编译代码并运行JUnit测试,则不会获取资源文件夹中的test.properties,我必须将它放在项目的根目录中才能工作。其次,适用于某些文件的代码,我想从一个文件夹或者jar中复制,是两组不同的代码。因此,为此操作执行JUnit测试方法是没用的,因为我可以使用不同的方式使其在测试用例中工作,并使其在另一个jar中工作。

我的test.properties有:

cssFileLocation =src/main/resources/all.css

我的production.properties有(可以将资源文件夹中的文件移动到Jar的根目录):

cssFileLocation=all.css

我的代码是以下方法,它应该将css文件移动到/static/all.css下的外部目录中:

 public static void copyCSS(String newCSSTargetLocation, String cssFileLocation) {
        File source = null;
        String line = "";
        String cssString = null;
        source = new File(cssFileLocation);

        File dest = new File(newCSSTargetLocation + "/static/all.css");
        logger.debug("Absoulte path of css file  : " + source.getAbsolutePath());
        /**
         * The Block below works when executing the jar
         */
        InputStream input;
        input = GeoUtils.class.getClassLoader().getResourceAsStream(cssFileLocation);

        StringBuilder sb = new StringBuilder("");
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(input));) {
            line = "";

            if (null == reader) {
                logger.debug("reader  is null");
            }

            while ((line = reader.readLine()) != null) {
                sb = sb.append(line);
                sb = sb.append("\n");
            }

            cssString = new String(sb);

        } catch (IOException | NullPointerException ex) {
            logger.error("Exception in Buffered reader writer ....");
            ex.printStackTrace();


        }

        /**
         * This Block works when doing compile and tests are run through
         * Surefire
         */
        try {
            cssString = FileUtils.readFileToString(source, "UTF-8");
        } catch (IOException ex) {
            logger.error("Exception occured when reading through new File " + cssFileLocation);
            ex.printStackTrace();
        }

        if (null == dest) {
            logger.debug("destination file is a null file Cannot proceed to create all.css in " + newCSSTargetLocation);
        } else {
            logger.debug(" dest not null " + dest.getAbsolutePath());
             try {
            FileUtils.writeStringToFile(dest, cssString, "UTF-8");
            logger.debug(" all.css created to new location  Through File Utils  >>" + dest.getAbsolutePath());
        } catch (IOException ex) {
            logger.error("Exception occured when writing to  " + dest.getAbsolutePath());
            ex.printStackTrace();
        }
        }


    }

运行在编译期间调用此方法的测试方法时出现的错误(mvn clean install)

ERROR [main] (GeoUtils.java:673) - Exception in Buffered reader writer ....
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:78)
        at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
        at com.sarm.lonelyplanet.common.GeoUtils.copyCSS(GeoUtils.java:658)
        at com.sarm.lonelyplanet.common.GeoUtilsTest.testCopyCSS(GeoUtilsTest.java:207)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
        at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)

1 个答案:

答案 0 :(得分:2)

以下是Maven的工作原理。

编译项目时,会将src/main/resources的内容复制到target/classes。运行单元测试时,target/classes是类路径的一部分。它也是您放入生产应用程序中的类路径中的jar的内容。

因此,无论您是在执行测试还是在生产中运行,项目中all.css中的文件src/main/resources都会在类路径的根目录中结束。所以你需要加载这个文件

SomeClass.getClassLoader().getResourceAsStream("all.css");

相同的代码和相同的路径在您的测试和生产中都能正常工作。您不应该使用文件IO来读取src / main / resources中的文件。这些不是真正的文件。它们是打算由类加载器加载的资源。