如何从一个读取lib中某个jar包里的配置文件。(是从jar包的外部去读)

时间:2021-06-28 18:33:03
项目迁移的过程中发现以前的代码维护性实在是差。
我把问题简化为以下这些简单的代码:

项目M 引用了项目 A.jar,这个A在lib目录里面
在A里面放置了一个配置文件test.properties, 就放在jar的根目录下。
A.jar 
|___test.properties



在M中有一段代码回去读取这个A.jar里的配置文件,简单一点就用下面这句话来调用。

public class ConfigUtil {
public static String getInstance() throws Exception{

String path = ConfigUtil.class.getResource("/").toString();
path  = path.substring(0, path.length()-8);//
System.out.println(path);//这里打印的结果显示可以拿到当前类的绝对路径
InputStream f = new FileInputStream("jar:"+path+"lib!/A.jar/"+"test.properties");
return "xxx";
}
}





现在报了file not found Exception
java.io.FileNotFoundException: jar:file:\file:\C:\project_material\test_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\M\WEB-INF\lib!\A.jar\test.properties (The filename, directory name, or volume label syntax is incorrect)

从出错的log可以看到它确实访问了eclipse tomcat 的发布路径。jar:file:\file:\C:\project_material\test_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\M\WEB-INF\lib


但是要如何读取这个路径下某个jar包里的文件?

7 个解决方案

#1



public class ConfigUtil {
public static String getInstance() throws Exception{

URL u = ConfigUtil.class.getClassLoader().getResource("test.properties");
System.out.println(u.getPath());
InputStream f = new FileInputStream(u.getPath());
return "xxx";
}
}




网上查了一下,换了上面这种写法,但是依然报错,在实际的代码里我需要把某个路径传个InputStream

java.io.FileNotFoundException: file:\C:\project_material\test_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\M\WEB-INF\lib\A.jar!\test.properties (The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.io.FileInputStream.<init>(FileInputStream.java:79)
at com.test.ConfigUtil.getInstance(ConfigUtil.java:16)
at org.apache.jsp.jsp._1_jsp._jspService(_1_jsp.java:65)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:662)

#2


jar是个ZIP压缩的文件,我该说的说完了。

#3


直接用path传值给FileInputStream 不行吗?

#4


自己顶一下

#5


你不会把A.jar拷贝到新项目的lib里面去吗

#6


import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import junit.framework.TestCase;

public class Debug extends TestCase
{
  public void test() throws Exception
  {
    //1.从外部jar包文件读取配置文件内容:
    //假设存在文件: E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/lib/log4j-1.2.16.jar
    //你可以这样读出jar包中的org/apache/log4j/xml/log4j.dtd文件的内容;
    byte[] data1 = readResource("E:/apache-tomcat-6.0.18/webapps/ROOT", "log4j-1.2.16.jar:org/apache/log4j/xml/log4j.dtd");
    System.out.println("E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/lib/log4j-1.2.16.jar包里的org/apache/log4j/xml/log4j.dtd内容如下: ");
    System.out.println(new String(data1));
    System.out.println();
    System.out.println();
    
    //2.从classes路径读取配置文件内容:
    //假设存在文件: E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/conf/log4j.properties,
    //你可以这样读出/conf/log4j.properties文件的内容;
    byte[] data2 = readResource("E:/apache-tomcat-6.0.18/webapps/ROOT", "/conf/log4j.properties");
    System.out.println("E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/conf/log4j.properties的内容如下: ");
    System.out.println(new String(data2));
    
  }

  /**
   * 从外部jar包或classes类路径下读取配置文件
   * @param applicationRootPath Web应用目录
   * @param className jar包及其资源文件相对路径或classes类路径下配置文件的相对路径
   * @return 配置文件的2进制内容
   */
  public static byte[] readResource(String applicationRootPath, String className)
  {
    String[] classNames = className.split(":");
    if (classNames[0].endsWith(".jar"))
    {
      if (classNames.length == 1)
      {
        String jarFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "lib" + File.separator + classNames[0];
        return readResourceOfFile(jarFilePath);
      }

      String jarFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "lib" + File.separator + classNames[0];
      return readResourceFromJar(jarFilePath, classNames[1]);
    }

    String classesFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + classNames[0];
    return readResourceOfFile(classesFilePath);
  }

  private static byte[] readResourceOfFile(String className)
  {
    byte[] arr_result = null;
    InputStream in = null;
    ByteArrayOutputStream fout = new ByteArrayOutputStream(8192);
    try
    {
      in = new FileInputStream(className);
      BufferedInputStream fin = new BufferedInputStream(in, 8192);

      byte[] data = new byte[8192];
      int count = 0;

      while (count >= 0)
      {
        count = fin.read(data);
        if (count > 0)
        {
          fout.write(data, 0, count);
        }
      }
      
      arr_result = fout.toByteArray();
    } catch (Exception e)
    {
      e.printStackTrace();
    } finally
    {
      if (in != null)try{in.close();} catch (Exception ex){}
      if (fout != null)try{fout.close();} catch (Exception ex){}
    }

    return arr_result;
  }

  private static byte[] readResourceFromJar(String jarFile, String className)
  {
    byte[] arr_result = null;
    try
    {
      ZipFile zipFile = new ZipFile(jarFile);
      try
      {
        ZipEntry zipEntry = zipFile.getEntry(className);
        if (zipEntry == null)return null;
        BufferedInputStream fin = new BufferedInputStream(zipFile.getInputStream(zipEntry), 8192);
        ByteArrayOutputStream fout = new ByteArrayOutputStream(8192);
        try
        {
          byte[] data = new byte[8192];
          int count = 0;

          while (count >= 0)
          {
            count = fin.read(data);
            if (count > 0)
            {
              fout.write(data, 0, count);
            }
          }
          arr_result = fout.toByteArray();
        } finally
        {
          fin.close();
          fout.close();
        }
      } finally
      {
        zipFile.close();
      }
    } catch (Exception e){}
    
    return arr_result;
  }
  
}

#7


老紫竹 正解   

#1



public class ConfigUtil {
public static String getInstance() throws Exception{

URL u = ConfigUtil.class.getClassLoader().getResource("test.properties");
System.out.println(u.getPath());
InputStream f = new FileInputStream(u.getPath());
return "xxx";
}
}




网上查了一下,换了上面这种写法,但是依然报错,在实际的代码里我需要把某个路径传个InputStream

java.io.FileNotFoundException: file:\C:\project_material\test_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\M\WEB-INF\lib\A.jar!\test.properties (The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.io.FileInputStream.<init>(FileInputStream.java:79)
at com.test.ConfigUtil.getInstance(ConfigUtil.java:16)
at org.apache.jsp.jsp._1_jsp._jspService(_1_jsp.java:65)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:662)

#2


jar是个ZIP压缩的文件,我该说的说完了。

#3


直接用path传值给FileInputStream 不行吗?

#4


自己顶一下

#5


你不会把A.jar拷贝到新项目的lib里面去吗

#6


import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import junit.framework.TestCase;

public class Debug extends TestCase
{
  public void test() throws Exception
  {
    //1.从外部jar包文件读取配置文件内容:
    //假设存在文件: E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/lib/log4j-1.2.16.jar
    //你可以这样读出jar包中的org/apache/log4j/xml/log4j.dtd文件的内容;
    byte[] data1 = readResource("E:/apache-tomcat-6.0.18/webapps/ROOT", "log4j-1.2.16.jar:org/apache/log4j/xml/log4j.dtd");
    System.out.println("E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/lib/log4j-1.2.16.jar包里的org/apache/log4j/xml/log4j.dtd内容如下: ");
    System.out.println(new String(data1));
    System.out.println();
    System.out.println();
    
    //2.从classes路径读取配置文件内容:
    //假设存在文件: E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/conf/log4j.properties,
    //你可以这样读出/conf/log4j.properties文件的内容;
    byte[] data2 = readResource("E:/apache-tomcat-6.0.18/webapps/ROOT", "/conf/log4j.properties");
    System.out.println("E:/apache-tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/conf/log4j.properties的内容如下: ");
    System.out.println(new String(data2));
    
  }

  /**
   * 从外部jar包或classes类路径下读取配置文件
   * @param applicationRootPath Web应用目录
   * @param className jar包及其资源文件相对路径或classes类路径下配置文件的相对路径
   * @return 配置文件的2进制内容
   */
  public static byte[] readResource(String applicationRootPath, String className)
  {
    String[] classNames = className.split(":");
    if (classNames[0].endsWith(".jar"))
    {
      if (classNames.length == 1)
      {
        String jarFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "lib" + File.separator + classNames[0];
        return readResourceOfFile(jarFilePath);
      }

      String jarFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "lib" + File.separator + classNames[0];
      return readResourceFromJar(jarFilePath, classNames[1]);
    }

    String classesFilePath = applicationRootPath + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + classNames[0];
    return readResourceOfFile(classesFilePath);
  }

  private static byte[] readResourceOfFile(String className)
  {
    byte[] arr_result = null;
    InputStream in = null;
    ByteArrayOutputStream fout = new ByteArrayOutputStream(8192);
    try
    {
      in = new FileInputStream(className);
      BufferedInputStream fin = new BufferedInputStream(in, 8192);

      byte[] data = new byte[8192];
      int count = 0;

      while (count >= 0)
      {
        count = fin.read(data);
        if (count > 0)
        {
          fout.write(data, 0, count);
        }
      }
      
      arr_result = fout.toByteArray();
    } catch (Exception e)
    {
      e.printStackTrace();
    } finally
    {
      if (in != null)try{in.close();} catch (Exception ex){}
      if (fout != null)try{fout.close();} catch (Exception ex){}
    }

    return arr_result;
  }

  private static byte[] readResourceFromJar(String jarFile, String className)
  {
    byte[] arr_result = null;
    try
    {
      ZipFile zipFile = new ZipFile(jarFile);
      try
      {
        ZipEntry zipEntry = zipFile.getEntry(className);
        if (zipEntry == null)return null;
        BufferedInputStream fin = new BufferedInputStream(zipFile.getInputStream(zipEntry), 8192);
        ByteArrayOutputStream fout = new ByteArrayOutputStream(8192);
        try
        {
          byte[] data = new byte[8192];
          int count = 0;

          while (count >= 0)
          {
            count = fin.read(data);
            if (count > 0)
            {
              fout.write(data, 0, count);
            }
          }
          arr_result = fout.toByteArray();
        } finally
        {
          fin.close();
          fout.close();
        }
      } finally
      {
        zipFile.close();
      }
    } catch (Exception e){}
    
    return arr_result;
  }
  
}

#7


老紫竹 正解