Task 858: .ZRX File Format
Task 858: .ZRX File Format
1. Properties of the .ZRX File Format
The .ZRX file format corresponds to the ZRXP data exchange format, a line-oriented text-based format designed for time series data, developed by Kisters. It uses ISO-8859-1 encoding and supports the exchange of various information, including time series values and metadata. The format is backward compatible, with all segments in a file required to use the same ZRXP version. Comments are denoted by lines starting with "##", and empty lines are ignored. The structure consists of one or more segments, each comprising a basic data header (lines starting with "#") and a time series value block.
The intrinsic properties are defined through keyword-value pairs in the header and column layouts in the data block. These properties include:
- SANR: Alphanumerical station number.
- SNAME: Station name.
- SWATER: River name.
- CDASA: Remote call logger/meter number.
- CDASANAME: DASA name.
- CCHANNEL: DASA channel name.
- CCHANNELNO: DASA channel number.
- CMW: Values per day for equidistant time series.
- CNAME: Parameter name.
- CNR: Parameter number.
- CUNIT: Unit of data value.
- REXCHANGE: Import number of import agent.
- RINVAL: Value for missing/invalid data (default: -777.0).
- RTIMELVL: Time series time level.
- XVLID: Internal time series ID.
- TSPATH: Absolute path in KiTSM.
- CTAG: Special tag.
- CTAGKEY: Special tag key.
- XTRUNCATE: Flag to remove existing data before import.
- METCODE: Metering code (BDEW energy market).
- METERNUMBER: Meter number (BDEW).
- EDIS: EDIS/OBIS code (BDEW).
- TZ: Time zone of timestamps.
- ZDATE: Timestamp of meter reading.
- ZRXPVERSION: ZRXP format version (mandatory).
- ZRXPCREATOR: Name of creation tool.
- LAYOUT: Defines column layout for the data block (mandatory).
- TASKID: Internal task identifier.
- SOURCESYSTEM: Designator of source system.
- SOURCEID: Time series identifier by source.
Column properties defined via LAYOUT (case-insensitive aliases):
- timestamp: Primary timestamp (format: yyyymmdd[hhmmss]).
- value: Primary numeric value.
- primary_status: Primary status code (integer 0–255).
- system_status: System status (string).
- additional_status: Additional status (string).
- interpolation_type: Interpolation type (integer).
- remark: Remarks (string).
- timestampoccurrence: Occurrence timestamp.
- occurrencecount: Reset number.
- member: Ensemble member identifier.
- forecast: Forecast timestamp.
- signature: Signature code.
- reset_number: Reset number.
- reset_timestamp: Reset timestamp.
- releaselevel: Release level.
- dispatchinfo: Dispatch information.
2. Direct Download Links for .ZRX Files
- https://raw.githubusercontent.com/jackieleng/zrxp/master/data/K-Greim-SG-cmd-2000-2004.zrx
- https://raw.githubusercontent.com/keithhb33/ZRX-Compiler/main/testFile.zrx (Note: This example uses a different interpretation of .ZRX as a simple file management script, but serves as an additional .ZRX file instance.)
3. Ghost Blog Embedded HTML JavaScript for Drag and Drop .ZRX File
4. Python Class for .ZRX File
import os
class ZRXFile:
def __init__(self, filepath):
self.filepath = filepath
self.header = {}
self.columns = []
self.data = []
self.encoding = 'iso-8859-1'
def read(self):
with open(self.filepath, 'r', encoding=self.encoding) as f:
content = f.readlines()
in_header = True
for line in content:
line = line.strip()
if line.startswith('##') or not line:
continue
if line.startswith('#'):
parts = line[1:].split('|*|') or line[1:].split(';*;')
for part in parts:
if '<' in part and '>' in part:
key, value = part.split('<', 1)[0], part.split('<', 1)[1].split('>')[0]
if key == 'LAYOUT':
self.columns = value.strip('()').split(',')
else:
self.header[key] = value
else:
if in_header:
in_header = False
values = line.split()
self.data.append(values)
return self.header, self.columns, self.data
def decode(self):
# Decoding is parsing the text content as per read method
return self.read()
def write(self, new_filepath=None):
if not new_filepath:
new_filepath = self.filepath
with open(new_filepath, 'w', encoding=self.encoding) as f:
for key, value in self.header.items():
f.write(f'#{key}<{value}>|*|\n')
if self.columns:
f.write(f'#LAYOUT({" ".join(self.columns)})\n')
for row in self.data:
f.write(' '.join(row) + '\n')
def print_properties(self):
print("Header Properties:")
for key, value in self.header.items():
print(f"{key}: {value}")
print("\nColumns:")
print(self.columns)
print("\nData Sample (first 5 rows):")
for row in self.data[:5]:
print(row)
# Example usage:
# zrx = ZRXFile('example.zrx')
# zrx.read()
# zrx.print_properties()
# zrx.write('new.zrx')
5. Java Class for .ZRX File
import java.io.*;
import java.util.*;
public class ZRXFile {
private String filepath;
private Map<String, String> header = new HashMap<>();
private List<String> columns = new ArrayList<>();
private List<List<String>> data = new ArrayList<>();
private String encoding = "ISO-8859-1";
public ZRXFile(String filepath) {
this.filepath = filepath;
}
public void read() throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filepath), encoding))) {
String line;
boolean inHeader = true;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.startsWith("##") || line.isEmpty()) continue;
if (line.startsWith("#")) {
String[] parts = line.substring(1).split("\\|\\*\\||;\\*;");
for (String part : parts) {
if (part.contains("<") && part.contains(">")) {
String key = part.substring(0, part.indexOf("<")).trim();
String value = part.substring(part.indexOf("<") + 1, part.indexOf(">")).trim();
if (key.equals("LAYOUT")) {
columns = Arrays.asList(value.replaceAll("[()]", "").split(","));
} else {
header.put(key, value);
}
}
}
} else {
if (inHeader) inHeader = false;
String[] values = line.split("\\s+");
data.add(Arrays.asList(values));
}
}
}
}
public void decode() throws IOException {
// Decoding is equivalent to reading the text content
read();
}
public void write(String newFilepath) throws IOException {
if (newFilepath == null) newFilepath = filepath;
try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(newFilepath), encoding))) {
for (Map.Entry<String, String> entry : header.entrySet()) {
writer.println("#" + entry.getKey() + "<" + entry.getValue() + ">|*|");
}
if (!columns.isEmpty()) {
writer.println("#LAYOUT(" + String.join(",", columns) + ")");
}
for (List<String> row : data) {
writer.println(String.join(" ", row));
}
}
}
public void printProperties() {
System.out.println("Header Properties:");
header.forEach((key, value) -> System.out.println(key + ": " + value));
System.out.println("\nColumns:");
System.out.println(columns);
System.out.println("\nData Sample (first 5 rows):");
for (int i = 0; i < Math.min(5, data.size()); i++) {
System.out.println(data.get(i));
}
}
// Example usage:
// public static void main(String[] args) throws IOException {
// ZRXFile zrx = new ZRXFile("example.zrx");
// zrx.read();
// zrx.printProperties();
// zrx.write("new.zrx");
// }
}
6. JavaScript Class for .ZRX File
class ZRXFile {
constructor(filepath) {
this.filepath = filepath;
this.header = {};
this.columns = [];
this.data = [];
this.encoding = 'ISO-8859-1'; // Note: JavaScript FileReader uses UTF-8 by default; use TextDecoder for ISO-8859-1 if needed
}
async read() {
const fs = require('fs'); // For Node.js
const content = fs.readFileSync(this.filepath, this.encoding);
const lines = content.split('\n');
let inHeader = true;
lines.forEach((line) => {
line = line.trim();
if (line.startsWith('##') || !line) return;
if (line.startsWith('#')) {
const parts = line.slice(1).split(/\|\*\|/);
parts.forEach((part) => {
const match = part.match(/(\w+)<([^>]+)>/);
if (match) {
const key = match[1];
const value = match[2];
if (key === 'LAYOUT') {
this.columns = value.replace(/[()]/g, '').split(',');
} else {
this.header[key] = value;
}
}
});
} else {
if (inHeader) inHeader = false;
const values = line.split(/\s+/).filter(Boolean);
if (values.length > 0) this.data.push(values);
}
});
}
decode() {
// Decoding is parsing as per read
return this.read();
}
write(newFilepath = this.filepath) {
const fs = require('fs'); // For Node.js
let content = '';
for (const [key, value] of Object.entries(this.header)) {
content += `#${key}<${value}>|*|\n`;
}
if (this.columns.length > 0) {
content += `#LAYOUT(${this.columns.join(',')})\n`;
}
this.data.forEach((row) => {
content += `${row.join(' ')}\n`;
});
fs.writeFileSync(newFilepath, content, this.encoding);
}
printProperties() {
console.log('Header Properties:');
console.log(this.header);
console.log('\nColumns:');
console.log(this.columns);
console.log('\nData Sample (first 5 rows):');
console.log(this.data.slice(0, 5));
}
}
// Example usage in Node.js:
// const zrx = new ZRXFile('example.zrx');
// await zrx.read();
// zrx.printProperties();
// zrx.write('new.zrx');
7. C Implementation for .ZRX File (Using Struct and Functions, as C Does Not Have Classes)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE 1024
#define MAX_KEYS 50
#define MAX_COLS 20
#define MAX_DATA_ROWS 1000 // Arbitrary limit for sample
typedef struct {
char *filepath;
char *encoding; // ISO-8859-1, but C file ops use default; assume ASCII compatible
struct {
char *key[MAX_KEYS];
char *value[MAX_KEYS];
int count;
} header;
char *columns[MAX_COLS];
int col_count;
char *data[MAX_DATA_ROWS][MAX_COLS];
int data_rows;
} ZRXFile;
ZRXFile* zrx_create(const char *filepath) {
ZRXFile *zrx = malloc(sizeof(ZRXFile));
zrx->filepath = strdup(filepath);
zrx->encoding = "ISO-8859-1"; // Note: C stdio doesn't handle encoding directly
zrx->header.count = 0;
zrx->col_count = 0;
zrx->data_rows = 0;
return zrx;
}
void zrx_destroy(ZRXFile *zrx) {
for (int i = 0; i < zrx->header.count; i++) {
free(zrx->header.key[i]);
free(zrx->header.value[i]);
}
for (int i = 0; i < zrx->col_count; i++) {
free(zrx->columns[i]);
}
for (int i = 0; i < zrx->data_rows; i++) {
for (int j = 0; j < zrx->col_count; j++) {
free(zrx->data[i][j]);
}
}
free(zrx->filepath);
free(zrx);
}
void zrx_read(ZRXFile *zrx) {
FILE *file = fopen(zrx->filepath, "r");
if (!file) return;
char line[MAX_LINE];
int in_header = 1;
while (fgets(line, MAX_LINE, file)) {
char *trimmed = line;
while (isspace(*trimmed)) trimmed++;
if (strncmp(trimmed, "##", 2) == 0 || *trimmed == '\0') continue;
if (*trimmed == '#') {
trimmed++;
char *token = strtok(trimmed, "|*| ;*;");
while (token) {
char *open = strchr(token, '<');
char *close = strchr(token, '>');
if (open && close) {
*open = '\0';
*close = '\0';
char *key = strdup(token);
char *value = strdup(open + 1);
if (strcmp(key, "LAYOUT") == 0) {
char *col_token = strtok(value, "(), ");
while (col_token && zrx->col_count < MAX_COLS) {
zrx->columns[zrx->col_count++] = strdup(col_token);
col_token = strtok(NULL, "(), ");
}
} else {
zrx->header.key[zrx->header.count] = key;
zrx->header.value[zrx->header.count++] = value;
}
}
token = strtok(NULL, "|*| ;*;");
}
} else {
if (in_header) in_header = 0;
if (zrx->data_rows >= MAX_DATA_ROWS) continue;
char *val_token = strtok(trimmed, " \t");
int col = 0;
while (val_token && col < zrx->col_count) {
zrx->data[zrx->data_rows][col++] = strdup(val_token);
val_token = strtok(NULL, " \t");
}
if (col > 0) zrx->data_rows++;
}
}
fclose(file);
}
void zrx_decode(ZRXFile *zrx) {
// Decoding is parsing as per read
zrx_read(zrx);
}
void zrx_write(ZRXFile *zrx, const char *new_filepath) {
const char *path = new_filepath ? new_filepath : zrx->filepath;
FILE *file = fopen(path, "w");
if (!file) return;
for (int i = 0; i < zrx->header.count; i++) {
fprintf(file, "#%s<%s>|*|\n", zrx->header.key[i], zrx->header.value[i]);
}
if (zrx->col_count > 0) {
fprintf(file, "#LAYOUT(");
for (int i = 0; i < zrx->col_count; i++) {
fprintf(file, "%s%s", zrx->columns[i], i < zrx->col_count - 1 ? "," : "");
}
fprintf(file, ")\n");
}
for (int i = 0; i < zrx->data_rows; i++) {
for (int j = 0; j < zrx->col_count; j++) {
fprintf(file, "%s ", zrx->data[i][j]);
}
fprintf(file, "\n");
}
fclose(file);
}
void zrx_print_properties(ZRXFile *zrx) {
printf("Header Properties:\n");
for (int i = 0; i < zrx->header.count; i++) {
printf("%s: %s\n", zrx->header.key[i], zrx->header.value[i]);
}
printf("\nColumns:\n");
for (int i = 0; i < zrx->col_count; i++) {
printf("%s ", zrx->columns[i]);
}
printf("\n\nData Sample (first 5 rows):\n");
for (int i = 0; i < 5 && i < zrx->data_rows; i++) {
for (int j = 0; j < zrx->col_count; j++) {
printf("%s ", zrx->data[i][j]);
}
printf("\n");
}
}
// Example usage:
// int main() {
// ZRXFile *zrx = zrx_create("example.zrx");
// zrx_read(zrx);
// zrx_print_properties(zrx);
// zrx_write(zrx, "new.zrx");
// zrx_destroy(zrx);
// return 0;
// }