Sto per creare un formato di file specifico per un particolare progetto.
Non ci sono metadati speciali relativi al file, poiché possono essere salvati nel database, in un file, ecc. Quindi l'estensione del file, la data, ecc. non hanno alcuna importanza: solo il contenuto lo fa.
Ora so che il formato avrà diverse iterazioni, quindi la prima cosa che sto facendo è progettarla con ulteriori versioni in mente.
Quello che ho pensato è il seguente:
<format-id> -> 4 bytes
<format-version> -> 1 byte
Ora la parte difficile: quando voglio analizzare qualsiasi versione del formato, cosa dovrei fare?
Ho pensato di utilizzare un PushbackInputStream
, leggere i primi 5 byte e recuperare il parser di versione appropriato sulla base di quei byte, quindi non leggere i byte e presentare il flusso "pristine" al parser effettivo. In questo modo posso testare i parser in modo indipendente senza usare il mio "parser-aggregator".
Esempio:
byte[] identifier = "ABCD".getBytes(UTF_8);
try (PushbackInputStream in = ...) {
byte[] header = IOUtils.readFully(in, new byte[5]);
in.unread(header);
if (!Arrays.equals(identifier, Arrays.copyOf(header, 4))) {
throw new UnknownFormatException();
}
int version = header[4];
getParser(version).parse(in);
}
Il secondo modo in cui ho pensato è di presentare l'avvio del flusso al parser e lasciarlo accettare o rifiutare di analizzare il resto del flusso:
try (PushbackInputStream in = ...) {
byte[] header = IOUtils.readFully(in, new byte[5]);
in.unread(header);
for (Parser parser: parsers) {
if (parser.accept(header)) {
parser.parse(in);
break;
}
}
}
La mia domanda è: esistono solide tecniche per implementare un parser multi-formato? Ad esempio, in che modo% sw_out% di Java Swing gestisce così tanti formati?
Note:
- Sto principalmente cercando di evitare ogni parser per cercare di analizzare il flusso. Non voglio assolutamente che ciò accada. Questa domanda risponde a questo, ma non è quello che voglio.