N formas de leer el contenido del archivo en Java

Prólogo

java Cuando contacté por primera vez  , estaba confundido acerca de la Fileruta relativa de una cosa  , qué directorio usar como referencia.

Con el desarrollo del modelo io, java de 1,7  nioutilización  Path, Paths y  Files así sucesivamente para facilitar io operación.

ClassLoader Usado para obtener class 文件 el io, también podemos usarlo para obtener el archivo io, de modo que podamos leer el contenido del archivo.

Contenido del diseño de este artículo.

  • File, ZipFile, JarFile leen la ruta relativa y el contenido absoluto del archivo de ruta.
  • ¿Cómo surgió System.getProperty ("user.dir")?
  • Rutas, Ruta, Archivos leen el contenido del archivo.
  • El cargador de clases obtiene el contenido del archivo, Class.getResourceAsStream y ClassLoader.getResourceAsStream.
  • Presente el modelo de delegación principal del cargador de clases y encuentre la lógica de carga correspondiente en el código.

El código <font color = red> se basa en  Mac 10.15.4JDK 1.8. </ font>

Obtener contenido de archivo basado en archivo

Obtener el contenido de la ruta absoluta es relativamente simple, obtenga directamente el archivo io y luego use la clase de herramienta para leer el contenido del archivo.

Obtener el contenido absoluto del archivo de ruta

final File file = new File("/Users/zhangpanqin/github/fly-java/demo.txt");
final byte[] bytes = cn.hutool.core.io.FileUtil.readBytes(file); System.out.println(new String(bytes, StandardCharsets.UTF_8)); 

Obtener el contenido de JarFile

JarFile La herencia se  ZipFile utiliza para obtener el contenido del paquete jar. Por ejemplo, quiero obtener el contenido de un archivo en un jar.


final File file = new File("/Users/zhangpanqin/github/fly-java/src/main/resources/fastjson-1.2.68.jar");
final JarFile jarFile = new JarFile(file); final JarEntry jarEntry = jarFile.getJarEntry("META-INF/LICENSE.txt"); final InputStream inputStream = jarFile.getInputStream(jarEntry); // 工具类是 hutool System.out.println(IoUtil.read(inputStream, StandardCharsets.UTF_8)); IoUtil.close(inputStream); 

Obtener contenido de ruta relativa

File.getAbsolutePath Mirando el código fuente, puede ver que la ruta relativa está realmente cosida al frente  System.getProperty("user.dir").

class UnixFileSystem extends FileSystem { public String resolve(File f) { if (isAbsolute(f)) return f.getPath(); return resolve(System.getProperty("user.dir"), f.getPath()); } } 

Mientras lo resolvamos  System.getProperty("user.dir"), el problema estará resuelto. La  introducción  user.dir en Java System Properties es el directorio de trabajo del usuario.

image-20200418232813977

<font color = red> ¿Cuál es el directorio de trabajo del usuario? Es el directorio donde se ejecuta el comando java. </ font> Ejecutando comandos en ese directorio, usr.dir será asignado como la ruta para ejecutar el comando por la máquina virtual java. /Users/zhangpanqin/github/fly-java/test Ejecuto el class archivo compilado en el  directorio  . -cp Especifique la ruta de classpath.

image-20200418233359327

nio lee el contenido del archivo

Path Se puede usar por analogía  File . Entonces Paths se puede obtener la  clase de herramienta  Path, y Files proporciona una API rica para archivos de operación crud  Path.

Obtener contenido de ruta absoluto

@Test
public void run33() throws IOException { final Path path = Paths.get("/Users/zhangpanqin/github/fly-java/demo.txt"); final byte[] bytes = Files.readAllBytes(path); System.out.println(new String(bytes,StandardCharsets.UTF_8)); } 

Obtener contenido de ruta relativa

Paths Al obtener una ruta relativa, la ruta no se  / inicia. También se puede entender como relativo a la  System.getProperty("user.dir") ruta.

public static void main(String[] args) { System.out.println(System.getProperty("user.dir")); System.out.println(Paths.get("").toAbsolutePath()); } 

image-20200419001203097

Obtener contenido del archivo basado en ClassLoader

ClassLoader.getResourceAsStream

// ClassLoader.getResourceAsStream java 1.8 源码
public InputStream getResourceAsStream(String name) { URL url = getResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } } 

Puede ver en el código que la lógica principal todavía está concentrada  getResource .

public URL getResource(String name) {
    URL url;
    if (parent != null) { url = parent.getResource(name); } else { url = getBootstrapResource(name); } if (url == null) { url = findResource(name); } return url; } 

La lógica del código anterior es lo que a menudo escuchamos  双亲委派机制. Deje  父类加载 ir para cargar los recursos primero, y luego encuéntrelo usted mismo si no puede encontrarlo. 类加载器单独讲.

El cargador de clases lee y lee el recurso, y primero busca desde la ruta de la que es responsable. Por ejemplo, el cargador de clases de la aplicación es  sun.misc.Launcher.AppClassLoader#AppClassLoader responsable de  classpath encontrar recursos. ¿Cuáles son las  ventajas File y  Pathdesventajas de los recursos de lectura del cargador de clases  ? Por ejemplo, cuando quiero obtener uno  jar de los recursos, es más problemático usar la ruta. El ClassLoader se puede encontrar desde la ruta responsable, o se puede encontrar en el paquete jar.

final URL resource = Test2.class.getClassLoader().getResource("com/alibaba/fastjson/JSONArray.class"); System.out.println(resource); 

El resultado de impresión anterior

jar:file:/Users/zhangpanqin/.m2/repository/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.jar!/com/alibaba/fastjson/JSONArray.class

También podemos encontrar un camino inputstream

@Test
public void run222(){ final InputStream resourceAsStream = Test2.class.getClassLoader().getResourceAsStream("META-INF/maven/com.alibaba/fastjson/pom.properties"); System.out.println(IoUtil.read(resourceAsStream, StandardCharsets.UTF_8)); } 

El resultado anterior es:

#Generated by Maven
#Mon Oct 07 22:09:36 CST 2019
version=1.2.62
groupId=com.alibaba
artifactId=fastjson

Class.getResourceAsStream

Class.getResourceAsStream El ClassLoader recurso de carga se llama realmente  , pero agregará la ruta a la ruta relativa al paquete donde se encuentra la clase actual.

Por ejemplo

// com.fly.study.java.classloader.Test2
@Test
public void run555(){ System.out.println(Test2.class.getResource("name")); } 

Los recursos reales encontrados son  com.fly.study.java.classloader.name. Relativo al recurso del paquete donde se encuentra la clase actual.

 

Cargador de clase

A menudo escuchamos sobre cargadores de clases  双亲委派模型.

img

¿Dónde puedo ver estas clases cargadas?

启动类加载器 No podemos ver el código fuente si no está implementado en el código Java.

sun.misc.Launcher clase tiene que sabemos  扩展类加载器 sun.misc.Launcher.ExtClassLoader y  应用类加载器 sun.misc.Launcher.AppClassLoader .

java.lang.ClassLoader#getSystemClassLoader Si observa el código, se devuelve el cargador de clase de aplicación real.

public static ClassLoader getSystemClassLoader() { initSystemClassLoader(); if (scl == null) { return null; } SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkClassLoaderPermission(scl, Reflection.getCallerClass()); } return scl; } private static synchronized void initSystemClassLoader() { if (!sclSet) { sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); if (l != null) { Throwable oops = null; scl = l.getClassLoader(); } } } 

La ejecución de la prueba de código devuelve el cargador de clases de la aplicación.

// sun.misc.Launcher$AppClassLoader@18b4aac2
@Test
public void run66(){
	System.out.println(ClassLoader.getSystemClassLoader());
}

Estos cargadores de tres clases son responsables de la carga de clases bajo diferentes rutas.

Introducción al cargador de clases de arranque

启动类加载器 BootClassLoader Responsable System.getProperty("sun.boot.class.path") de la carga de clases. Esa es la siguiente categoría.

${JAVA_HOME}/jre/lib/*.jar Y  ${JAVA_HOME}/jre/classes carga de clase.

/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/resources.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/sunrsasign.jar /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jsse.jar /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jce.jar /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/charsets.jar /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/jfr.jar /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/classes 
@Test
public void run77() { final URLClassPath bootstrapClassPath = Launcher.getBootstrapClassPath(); final URL[] urLs = bootstrapClassPath.getURLs(); Stream.of(urLs).forEach(item->{ System.out.println(item.getFile()); }); } 

Cargador de clase de extensión

扩展类加载器 sun.misc.Launcher.ExtClassLoader Es la System.getProperty("java.ext.dirs") clase de carga  .

@Test
public void run99() { final String property = System.getProperty("java.ext.dirs"); final String[] split = property.split(":"); Stream.of(split).forEach(item -> { System.out.println(item); }); } 
/Users/zhangpanqin/Library/Java/Extensions
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/ext
/Library/Java/Extensions
/Network/Library/Java/Extensions
/System/Library/Java/Extensions
/usr/lib/java

Cargador de clase de aplicación

应用类加载器 sun.misc.Launcher.AppClassLoader Cargando System.getProperty("java.class.path");

# -cp 指定 classpath 路径,多个路径可以使用 : 分开(linux 下为 :,window 下为 ;),
java -cp /Users/zhangpanqin/github/fly-java/target/classes com.fly.study.java.classloader.Test2 

 

Supongo que te gusta

Origin www.cnblogs.com/app7899/p/12732593.html
Recomendado
Clasificación