una txt texto separado por modificar linea leer guardar especifica ejemplos como comas caracter archivos archivo java oop configuration initialization runtime

txt - leer una linea especifica de un archivo en java



¿Cuál es la mejor manera de leer los parámetros de configuración del archivo de configuración en Java? (10)

Supongamos que hasta el momento de la ejecución no sabemos cuáles son los detalles de la configuración (el usuario puede necesitar configurar estos parámetros en el archivo de config antes de ejecutar la aplicación.

Quiero leer esos detalles de configuración y necesito volver a utilizarlos donde los necesite en mi aplicación. Para eso quiero hacerlos como constantes globales ( public static final ).

Entonces, mi duda es, ¿hay alguna implicaciones de rendimiento si leo desde el archivo de config directamente desde la clase requerida? dado que los valores de tiempo de ejecución no puedo poner directamente en una Interface separada.

Estoy pensando que tendrá un impacto en el rendimiento. Por favor sugiérame una mejor manera de hacer esto.

ACTUALIZACIÓN: ¿Puedo usar una clase final separada para los detalles de configuración? poniendo todos los detalles de configuración como constantes en una public final class separada
(Para leer todos los detalles de configuración a la vez desde el archivo de configuración y almacenarlos como constantes globales para su uso posterior en la aplicación)


Poner las claves de configuración directamente en las clases es malo: las claves de configuración se dispersarán sobre el código. La mejor práctica es la separación del código de la aplicación y el código de configuración. Por lo general, se utiliza un marco de inyección de dependencia como la primavera. Carga un archivo de configuración y construye los objetos usando valores de configuración. Si necesita algún valor de configuración en su clase, debe crear un setter para este valor. Spring establecerá este valor durante la inicialización del contexto.


Solo será un gasto de tiempo si los coloca en un archivo de propiedades y lee el archivo al inicio de su aplicación e inicializa todos los parámetros como parámetros del sistema ( System.setProperty ) y luego define constantes en su código como

public static final String MY_CONST = System.getProperty("my.const");

Pero asegúrese de la inicialización al inicio de su aplicación antes de que se cargue cualquier otra clase.


Una forma más es definir una clase y leer el archivo de propiedades en esa clase. Esta clase debe estar en el nivel de Aplicación y se puede marcar como Singleton. Marcar la clase como Singleton evitará que se creen varias instancias.


¿Qué tipo de archivo de configuración tienes en mente? Si se trata de un archivo de propiedades, esto podría ser adecuado para usted:

public class Configuration { // the configuration file is stored in the root of the class path as a .properties file private static final String CONFIGURATION_FILE = "/configuration.properties"; private static final Properties properties; // use static initializer to read the configuration file when the class is loaded static { properties = new Properties(); try (InputStream inputStream = Configuration.class.getResourceAsStream(CONFIGURATION_FILE)) { properties.load(inputStream); } catch (IOException e) { throw new RuntimeException("Failed to read file " + CONFIGURATION_FILE, e); } } public static Map<String, String> getConfiguration() { // ugly workaround to get String as generics Map temp = properties; Map<String, String> map = new HashMap<String, String>(temp); // prevent the returned configuration from being modified return Collections.unmodifiableMap(map); } public static String getConfigurationValue(String key) { return properties.getProperty(key); } // private constructor to prevent initialization private Configuration() { } }

También podría devolver el objeto Properties inmediatamente desde el método getConfiguration() , pero luego podría ser modificado por el código que lo acceda. Collections.unmodifiableMap() no hace que la configuración sea constante (dado que la instancia de Properties obtiene sus valores mediante el método load() vez creada), sin embargo, dado que está empaquetada en un mapa no modificable, otras clases no pueden cambiar la configuración .


¿Alguna vez has oído hablar de la configuración de Apache commons http://commons.apache.org/proper/commons-configuration/ ? Es el mejor lector de configuración que he encontrado e incluso lo estoy usando en mi aplicación que se está ejecutando desde 1 año. Nunca he encontrado ningún problema, muy fácil de entender y usar, gran rendimiento. Sé que es un poco dependiente de tu aplicación, pero créeme, te gustará.

Todo lo que necesitas hacer es

Configuration config = new ConfigSelector().getPropertiesConfiguration(configFilePath); String value = config.getString("key"); int value1 = config.getInt("key1"); String[] value2 = config.getStringArray("key2"); List<Object> value3 = config.getList("key3");

Y eso es. Su objeto de configuración mantendrá todos los valores de configuración y puede pasar ese objeto a tantas clases como desee. Con tantos métodos útiles disponibles, puede extraer el tipo de clave que desee.


protected java.util.Properties loadParams() throws IOException { // Loads a ResourceBundle and creates Properties from it Properties prop = new Properties(); URL propertiesFileURL = this.getClass().getResource("/conf/config.properties"); prop.load(new FileInputStream(new File(propertiesFileURL.getPath()))); return prop; } Properties prop = loadParams(); String prop1=(String) prop.get("x.y.z");


Bueno, este es un gran problema que se enfrenta en la vida de cada uno una vez en un testamento. Ahora llegando al problema, esto se puede resolver creando una clase singleton que tenga variables de instancia iguales a las del archivo de configuración con valores predeterminados. En segundo lugar, esta clase debe tener un método como getInstance() que lee las propiedades una vez y cada vez devuelve el mismo objeto, si existe. Para leer el archivo, podemos usar la variable del entorno para obtener una ruta o algo así como System.getenv("Config_path"); . La lectura de las propiedades (método readProperties() ) debe leer cada elemento del archivo de configuración y establecer el valor en las variables de instancia del objeto singleton. Entonces, un solo objeto contiene el valor de todos los parámetros de configuración y, además, si el parámetro está vacío, se considera el valor predeterminado.


Hay diferentes tipos de configuración.

Por lo general, se necesita algún tipo de configuración de arranque, por ejemplo, para conectarse a una base de datos o servicio, para poder iniciar la aplicación. La forma J2EE de especificar los parámetros de conexión de la base de datos es a través de un ''origen de datos'' especificado en el registro JNDI de su contenedor (Glassfish, JBoss, Websphere, ...). Esta fuente de datos se busca por nombre en su persistence.xml. En aplicaciones que no son J2EE, es más común especificarlas en un contexto Spring o incluso en un archivo .properties. En cualquier caso, generalmente necesita algo para conectar su aplicación a algún tipo de almacén de datos.

Después de realizar una búsqueda en un almacén de datos, una opción es administrar los valores de configuración dentro de este almacén de datos. Por ejemplo, si tiene una base de datos, puede usar una tabla separada (representada por ejemplo, una entidad JPA en su aplicación) para los valores de configuración. Si no quiere / necesita esta flexibilidad, puede usar un archivo .properties simple para esto. Existe un buen soporte para archivos .properties en Java ( ResourceBundle ) y en frameworks como Spring . El ResourceBundle de vanilla solo carga las propiedades una vez, el Spring Helper ofrece almacenamiento en caché y recarga configurables (esto ayuda con el aspecto de rendimiento que usted mencionó). Nota: también puede usar Propiedades respaldadas por un almacén de datos en lugar de un archivo.

A menudo ambos enfoques coexisten en una aplicación. Los valores que nunca cambian dentro de una aplicación implementada (como el nombre de la aplicación) se pueden leer desde un archivo de propiedades. Es posible que los valores que un planificador de aplicaciones necesite cambiar en tiempo de ejecución sin volver a implementarlos (por ejemplo, el intervalo de tiempo de espera de la sesión) se conserven mejor en un archivo .properties recargable o en una base de datos. Los valores que pueden ser cambiados por los usuarios de la aplicación deben mantenerse en el almacén de datos de la aplicación y generalmente tienen una pantalla en la aplicación para editarlos.

Así que mi consejo es separar los ajustes de configuración en categorías (por ejemplo, arranque, implementación, tiempo de ejecución y aplicación) y seleccionar un mecanismo apropiado para gestionarlos. Esto también depende del alcance de su aplicación, es decir, ¿es una aplicación web J2EE, una aplicación de escritorio, una utilidad de línea de comandos, un proceso por lotes?


Recomiendo usar JAXB o un marco de enlace similar que funcione con archivos basados ​​en texto. Como la implementación de JAXB es parte del JRE, es bastante fácil de usar. Como Denis desaconsejo las claves de configuración.

Aquí hay un ejemplo simple de una forma sencilla y fácil de usar para configurar su aplicación con XML y JAXB. Cuando utiliza un marco DI, puede simplemente agregar un objeto de configuración similar al contexto DI.

@XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class ApplicationConfig { private static final JAXBContext CONTEXT; public static final ApplicationConfig INSTANCE; // configuration properties with defaults private int number = 0; private String text = "default"; @XmlElementWrapper @XmlElement(name = "text") private List<String> texts = new ArrayList<>(Arrays.asList("default1", "default2")); ApplicationConfig() { } static { try { CONTEXT = JAXBContext.newInstance(ApplicationConfig.class); } catch (JAXBException ex) { throw new IllegalStateException("JAXB context for " + ApplicationConfig.class + " unavailable.", ex); } File applicationConfigFile = new File(System.getProperty("config", new File(System.getProperty("user.dir"), "config.xml").toString())); if (applicationConfigFile.exists()) { INSTANCE = loadConfig(applicationConfigFile); } else { INSTANCE = new ApplicationConfig(); } } public int getNumber() { return number; } public String getText() { return text; } public List<String> getTexts() { return Collections.unmodifiableList(texts); } public static ApplicationConfig loadConfig(File file) { try { return (ApplicationConfig) CONTEXT.createUnmarshaller().unmarshal(file); } catch (JAXBException ex) { throw new IllegalArgumentException("Could not load configuration from " + file + ".", ex); } } // usage public static void main(String[] args) { System.out.println(ApplicationConfig.INSTANCE.getNumber()); System.out.println(ApplicationConfig.INSTANCE.getText()); System.out.println(ApplicationConfig.INSTANCE.getTexts()); } }

El archivo de configuración se ve así:

<?xml version="1.0" encoding="UTF-8"?> <applicationConfig> <number>12</number> <text>Test</text> <texts> <text>Test 1</text> <text>Test 2</text> </texts> </applicationConfig>


Estoy pensando que impactará en el rendimiento.

Dudo que esto sea cierto.

Asumiendo que la aplicación lee el archivo de configuración solo una vez al inicio, el tiempo necesario para leer el archivo probablemente sea irrelevante para el rendimiento general de su aplicación. De hecho, cuanto más tiempo se ejecute la aplicación, menos importante será el tiempo de inicio.

El consejo estándar es optimizar solo el rendimiento de la aplicación cuando se tiene evidencia concreta (es decir, mediciones) para decir que el rendimiento es un problema importante. Luego, solo optimice las partes de su código que los perfiles le dicen que realmente es un cuello de botella de rendimiento.

¿Puedo usar una clase final separada para los detalles de configuración?

Sí, es posible hacer eso. Nadie va a detenerte 1 . Sin embargo, es una mala idea. Cualquier cosa que signifique que necesita recompilar su código para cambiar los parámetros de configuración es una mala idea. IMO.

Para leer todos los detalles de configuración a la vez desde el archivo de configuración y almacenarlos como constantes globales para su uso posterior en la aplicación.

Ah ... así que quiero leer los valores de las "constantes" en lugar de cablearlos.

Sí, eso es posible. Y tiene más sentido que los parámetros de configuración de cableado en el código. Pero todavía no es una buena idea (IMO).

¿Por qué? Bueno, veamos cómo debe ser el código:

public final class Config { public static final int CONST_1; public static final String CONST_2; static { int c1; String c2; try (Scanner s = new Scanner(new File("config.txt"))) { c1 = s.nextInt(); c2 = s.next(); } catch (IOException ex) { throw RuntimeException("Cannot load config properties", ex); } CONST_1 = c1; CONST_2 = c2; } }

La primera observación es que no importa que la clase sea final . Está declarando los campos como final que los hace constantes. (Declarar la clase como final evita la creación de subclases, pero eso no tiene ningún impacto en los campos static . Los campos estáticos no se ven afectados por la herencia).

La siguiente observación es que este código es frágil en varios aspectos:

  • Si algo sale mal en el bloque de inicializador estático. la excepción sin marcar lanzada por el bloque se envolverá como un ExceptionInInitializerError (sí ... es un Error !!) y la clase Config se marcará como errónea.

  • Si eso sucede, no hay una esperanza real de recuperación, y posiblemente incluso una mala idea para tratar de diagnosticar el Error .

  • El código anterior se ejecuta cuando se inicializa la clase Config , pero determinar cuándo ocurre puede ser complicado.

  • Si el nombre de archivo de la configuración es un parámetro, entonces tiene el problema de obtener el valor del parámetro ... antes de que se inicie la inicialización estática.

A continuación, el código es bastante complicado en comparación con la carga del estado en variables de instancia. Y ese desorden es en gran parte el resultado de tener que trabajar dentro de las limitaciones de los inicializadores estáticos. Así es como se ve el código si en su lugar usa variables de instancia final .

public final class Config { public final int CONST_1; public final String CONST_2; public Config(File file) throws IOException { try (Scanner s = new Scanner(file)) { CONST_1 = s.nextInt(); CONST_2 = s.next(); } } }

Finalmente, los beneficios de rendimiento de static final campos static final sobre los campos final son pequeños:

  • probablemente una o dos instrucciones de la máquina cada vez que accedes a una de las constantes,

  • posiblemente nada si el compilador JIT es inteligente, y usted maneja la referencia de Config singleton de manera apropiada.

En cualquier caso, en la gran mayoría de los casos, los beneficios serán insignificantes.

1 - OK ... si su código es revisado por código, entonces es probable que alguien lo detenga.