2011-12-15 25 views
6

Tengo dos carpetas de recursos.Crear archivo en recursos/carpeta de origen en Java mediante programación

src - aquí están mis archivos .java

recursos - aquí están mis archivos de recursos (imágenes, .properties) organizados en carpetas (paquetes).

¿Hay una manera de agregar mediante programación presentar otra .properties en esa carpeta de recursos?

que hemos probado algo como esto:

public static void savePropertiesToFile(Properties properties, File propertiesFile) throws IOException { 
     FileOutputStream out = new FileOutputStream(propertiesFile); 
     properties.store(out, null); 
     out.close(); 
    } 

y antes de que se creó:

new File("/folderInResources/newProperties.properties"); 

Pero parece que para la vía de acceso del sistema de archivos. ¿Cómo puedo obligarlo a buscar en la carpeta de recursos?

EDIT: Déjenme decir de qué se trata. Tengo una aplicación GUI y apoyo 2 idiomas (2 archivos .properties en la carpeta de recursos). Ahora agregué una opción que el usuario puede traducir fácilmente la aplicación y cuando termina guardo esas nuevas .properties en un disco en alguna carpeta oculta y lo leo desde allí. Pero esperaba poder guardar esos nuevos archivos .properties (nuevo idioma) junto a los idiomas actuales (carpeta de recursos). Tengo una clase de Mensajes estáticos que sabe cómo cargar recursos tanto desde el disco como desde los predeterminados en la carpeta de recursos. Pero si el usuario toma este archivo .jar en otra máquina, no tendría esos nuevos lenguajes, ya que están en el disco de esa computadora, no dentro del archivo .jar.

Respuesta

0

Los recursos se cargan a través de un cargador de clases, y el cargador de clase por defecto almacena en caché en gran medida.

usted necesita su propio cargador de clases con el comportamiento que necesita, para leer los recursos de un sistema de archivos no estático.

+0

@ Thorbjørn Ravn Andersen Si pruebo esto: 'MyClass.class.getClassLoader()' No veo ningún método que me de una ruta. – vale4674

+0

No puede escribir recursos. Sin embargo, puede tener un cargador de clases que carga recursos desde un sistema de archivos. –

0

problema sería la ruta de clase puede contener varios directorios raíz tan distintiva que uno para almacenar sería difícil sin un archivo o directorio existente.

Si ha cargado un archivo existente.

File existingFile = ...; 
File parentDirectory = existingFile.getParentFile(); 
new File(parentDirectory, "newProperties.properties"); 

De lo contrario, intente obtener un control en un directorio que sabe que es único en el directorio de recursos. (No estoy seguro de si esto funciona)

URL url = this.getClass().getResource("/parentDirectory"); 
File parentDirectory = new File(new URI(url.toString())); 
new File(parentDirectory, "newProperties.properties"); 
+0

@ Lionel Port Probé esta combinación y no funciona. \t \t 'URL url = FilesUtil.class.getResource ("/messages/messages.properties "); \t \t System.out.println (url); \t \t Archivo = archivo nuevo (url.toURI()); \t \t System.out.println (archivo); ' La primera salida me da la ruta absoluta en el disco, pero cuando trato de hacer un archivo de él, me da un' java.lang.IllegalArgumentException: URI tiene una excepción del componente de autoridad. Parece que Java no puede escribir dentro de su área de trabajo (archivo .jar). – vale4674

+0

Sí, solo funcionará si los archivos de propiedades están en un directorio expandido para el que tiene permiso de escritura. Lo siento, no me di cuenta de que estabas tratando de actualizar el archivo jar. –

+0

Se puede simplificar como; 'new File (parentDirectoryUrl.getFile())' – Ducaz035

6

Como han mencionado otras personas, los recursos se obtienen a través de un ClassLoader. Lo que las dos respuestas actuales han fracasado a la tensión, sin embargo, es estos puntos:

  • cargadores de clases están destinadas a abstracta el proceso de obtención de clases y otros recursos. Un recurso no tiene que ser un archivo en un sistema de archivos; puede ser una URL remota, o cualquier otra cosa que usted u otra persona pueda implementar ampliando java.lang.ClassLoader. Existen
  • cargadores de clases en una cadena de delegación hijo/padre. El comportamiento normal de un ClassLoader es intentar primero obtener el recurso del padre y solo luego buscar sus propios recursos, pero algunos cargadores de clases hacen el orden opuesto (por ejemplo, en contenedores de servlet).En cualquier caso, necesitaría identificar el lugar del cargador de clases para obtener cosas en las que le gustaría poner cosas, e incluso entonces otro cargador de clases superior o inferior podría "robar" las solicitudes de recursos de su código cliente.
  • Como señala Lionel Port, incluso un solo ClassLoader puede tener múltiples ubicaciones desde las que carga cosas.
  • Los ClassLoaders se usan para, bueno, cargar clases. Si su programa puede escribir archivos en una ubicación desde donde se cargan las clases, esto puede convertirse fácilmente en un riesgo de seguridad, ya que podría ser posible que un usuario inserte código en su aplicación en ejecución.

Versión corta: no lo hagas. Escribe una interfaz más abstracta para el concepto de "repositorio de material similar a un recurso del que puedo obtener material" y una subinterfaz para "depósito de material similar a un recurso del que puedo obtener material, pero también agregar cosas". Implemente el último de una manera que use ClassLoader.getContextClassLoader().getResource() (para buscar en el classpath) y, si eso falla, utiliza algún otro mecanismo para obtener cosas que el programa puede haber agregado desde alguna ubicación.

+0

@ sacundim He editado mi pregunta porque el comentario es demasiado grande. – vale4674

0

Cortar la carpeta principal del proyecto de las subcarpetas compilados ("/ target/classes", "meta/test-clases") y que tiene la ruta básica para reconstruir sus archivos de proyectos con:

import java.io.File; 
import java.io.IOException; 
import java.net.URISyntaxException; 

public class SubfolderCreator { 

public static void main(String... args) throws URISyntaxException, IOException { 
    File newResourceFolder = createResourceSubFolder("newFolder"); 
} 

private static File createResourceSubFolder(String folderName) throws URISyntaxException, IOException { 
    java.net.URL url = SubfolderCreator.class.getResource("/EXISTING_SUBFOLDER/"); 
    File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile(); 
    String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0]; 
    File testResultsFolder = new File(projectFolder + "src/test/resources/" + folderName); 
    if (!testResultsFolder.exists()) { 
     testResultsFolder.mkdir(); 
    } 
    return testResultsFolder; 
} 
} 
0

El El siguiente código se escribe en el directorio classes, junto con los archivos de clase.

Como han notado otros, tenga cuidado de sobrescribir los archivos de clase. Lo mejor es poner sus nuevos archivos en un directorio separado; sin embargo, ese directorio ya debe existir. Para crearlo, cree un subdirectorio dentro de los recursos en la fuente, quizás conteniendo un archivo vacío. Por ejemplo src\main\resources\dir\empty.txt.

public class WriteResource { 
    public static void main(String[] args) throws FileNotFoundException { 
     String thing = "Text to write to the file"; 
     String dir = WriteResource.class.getResource("/").getFile(); 
     //String dir = WriteResource.class.getResource("/dir").getFile(); 
     OutputStream os = new FileOutputStream(dir + "/file.txt"); 
     final PrintStream printStream = new PrintStream(os); 
     printStream.println(thing); 
     printStream.close(); 
    } 
} 

Esto hace el truco, pero me daría miedo implementar esto fuera de un entorno estrictamente controlado. ¡Realmente no me gusta la idea de que personas no autorizadas escriban en mi directorio classes!

Cuestiones relacionadas