Data formats

Java properties

Java .properties files read and written: Spring settings and translation bundles, with continued lines and \u escapes.

Version 1.0.0 · 3 functions · 1 crate

#config#translations#import#java

Functions

What use java_properties.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use properties_parse, properties_read_file from java_properties (Quillo 0.6).

properties_parse(text: str) → mapor an error

.properties text as a map of text: key=value, key: value and key value lines, # and ! comments, lines continued with \, and \uXXXX escapes read. A key given twice keeps the last.

properties_read_file(path: str) → mapor an error

A .properties file read as properties_parse reads text. Java's own files are ISO-8859-1 before Java 9 and UTF-8 since: both are read (bytes that are not UTF-8 are taken as ISO-8859-1).

properties_write(values: map, comment: str) → str

A map as .properties text, keys sorted, with comment (if not empty) as # lines at the top. Characters outside ASCII are written as \uXXXX, so every Java version reads the file the same; =, : and spaces in keys, a space starting a value, and line breaks are escaped.

Get it

$ quillo install java_properties               # java_properties.qwer into this folder$ quillo install java_properties --example     # and its example, java_properties.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/java_properties.qwer$ curl -O https://quillolang.org/plugins/files/java_properties.qwe$ curl -O https://quillolang.org/plugins/files/java_properties_sample.properties

Then, in your program, all of it or only what you call:

main.qwe
use java_properties.qweruse properties_parse, properties_read_file from java_properties      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
java-properties = "2"

Example

java_properties.qwe
// Settings and translations moved over from a Java (Spring) service.////   quillo run java_properties.qwe      then open http://localhost:8080/settingsuse "java_properties.qwer"route GET /settings {    let p = properties_read_file("java_properties_sample.properties")?    { port: int(p["server.port"])?, database: p["spring.datasource.url"], user: p["spring.datasource.username"], welcome: p["app.welcome"], greeting: p["greeting.de"], uploads: p["path.uploads"] }}route GET /messages_de.properties = respond(200, properties_write({ "cart.title": "Warenkorb", "cart.empty": "Ihr Warenkorb ist leer.", "checkout.pay": "Jetzt bezahlen: 12,50 €" }, "German messages, made by Quillo"), { "content-type": "text/plain; charset=iso-8859-1" })route GET /roundtrip {    let p = properties_read_file("java_properties_sample.properties")?    properties_parse(properties_write(p, ""))? == p}
$ quillo run java_properties.qwe$ curl 'localhost:8080/settings'$ curl 'localhost:8080/messages_de.properties'

Source

java_properties.qwer
//! Java .properties files read and written: Spring's application.properties, translation bundles (messages_de.properties) with their \u escapes, and build settings.//! version: 1.0.0//!//! [dependencies]//! java-properties = "2"use std::collections::{BTreeMap, HashMap};/// Files up to 10 MB are read.const MAX: usize = 10 * 1024 * 1024;/// .properties text as a map of text: `key=value`, `key: value` and `key value` lines, `#` and `!` comments, lines continued/// with `\`, and `\uXXXX` escapes read. A key given twice keeps the last.pub fn properties_parse(text: &str) -> Result<HashMap<String, String>, String> {    if text.len() > MAX {        return Err(".properties files up to 10 MB".into());    }    java_properties::read(std::io::BufReader::new(text.as_bytes())).map_err(|e| format!("not a .properties text: {}", e))}/// A .properties file read as properties_parse reads text. Java's own files are ISO-8859-1 before Java 9 and UTF-8 since:/// both are read (bytes that are not UTF-8 are taken as ISO-8859-1).pub fn properties_read_file(path: &str) -> Result<HashMap<String, String>, String> {    let bytes = std::fs::read(path).map_err(|e| format!("{}: {}", path, e))?;    if bytes.len() > MAX {        return Err(format!("{}: .properties files up to 10 MB", path));    }    let text = match String::from_utf8(bytes) {        Ok(t) => t,        Err(e) => e.into_bytes().iter().map(|&b| b as char).collect(),    };    properties_parse(&text)}fn escape(s: &str, key: bool, out: &mut String) {    for (i, c) in s.chars().enumerate() {        match c {            '\\' => out.push_str("\\\\"),            '\n' => out.push_str("\\n"),            '\r' => out.push_str("\\r"),            '\t' => out.push_str("\\t"),            '\x0c' => out.push_str("\\f"),            '=' | ':' if key => { out.push('\\'); out.push(c); }            '#' | '!' if key && i == 0 => { out.push('\\'); out.push(c); }            ' ' if key || i == 0 => out.push_str("\\ "),            c if (c as u32) < 0x20 || (c as u32) > 0x7e => {                let mut buf = [0u16; 2];                for u in c.encode_utf16(&mut buf) {                    out.push_str(&format!("\\u{:04x}", u));                }            }            c => out.push(c),        }    }}/// A map as .properties text, keys sorted, with `comment` (if not empty) as `#` lines at the top. Characters outside ASCII/// are written as `\uXXXX`, so every Java version reads the file the same; `=`, `:` and spaces in keys, a space starting a/// value, and line breaks are escaped.pub fn properties_write(values: std::collections::HashMap<String, String>, comment: &str) -> String {    let mut out = String::new();    for line in comment.lines() {        out.push_str("# ");        escape(line, false, &mut out);        out.push('\n');    }    let sorted: BTreeMap<&String, &String> = values.iter().collect();    for (k, v) in sorted {        escape(k, true, &mut out);        out.push('=');        escape(v, false, &mut out);        out.push('\n');    }    out}
Thread
68Useful? Like it, or add to its thread below.

Thread 0 posts

On Java properties: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.