Daten unter Java in ein Byte-Array umwandeln

Für ein Projekt wollte ich eine Liste von long-Werten unter Java in ein einzelnes Byte-Array umwandeln. Dafür kann unter Java die Klasse ByteBuffer genutzt werden. In diesem Beispiel wird eine Liste namens dataStream definiert:

List dataStream = new ArrayList<>();

In dieser Liste befinden sich eine unbestimmte Anzahl von Werten. Mit der Klasse ByteBuffer kann diese Liste bzw. die Werte in der Liste in ein Byte-Array überführt werden:

ByteBuffer byteBuffer = ByteBuffer.allocate(dataStream.size() * 8);

for(long value: dataStream) {
	byteBuffer.putLong(value);
}

byte[] array = byteBuffer.array();

Im ersten Schritt wird der ByteBuffer mit einer Kapazität angelegt, welcher der Größe der long-Werte in Byte entspricht. Anschließend werden die long-Werte in den ByteBuffer geschrieben. Ist dies geschehen kann ein Byte-Array aus dem ByteBuffer erstellt werden. Damit ist die Umwandlung abgeschlossen.

Konvertierungen zwischen alter und neuer Datums- und Zeit-API

Seit Java 8 verfügt die Programmiersprache über eine sinnvolle Datums- und Zeit-API. In den meisten Fällen kann diese API ohne weitere Probleme genutzt werden. Problematisch wird es nur, wenn die neue API im Zusammenhang mit Legacy-Code genutzt werden soll. Meist wird dort die Klasse Date aus dem Package java.util genutzt. Damit werden Methoden benötigt, um eine Brücke von der alten zur neuen API und umgekehrt zu schlagen. Um ein Date in eine LocalDateTime umzuwandeln, kann folgende Methode genutzt werden:

public static LocalDateTime convertToLocalDateTime(Date date) {
    return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}

Soll der Wert, welcher in der LocalDateTime gespeichert ist, wieder in ein Date-Objekt konvertiert werden, kann folgende Methode genutzt werden:

public static Date convertToDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

Bei diesen Konvertierungsmethoden ist zu beachten, dass die Zeitzonen bei der Konvertierung ignoriert werden. Stattdessen wird die Konvertierung mit der Standardzeitzone des Systems durchgeführt. Für die Konvertierung unter Berücksichtigung und Speicherung der Zeitzonen kann die Klasse ZonedDateTime genutzt werden. Die entsprechenden Methoden zur Konvertierung wären folgende:

public static ZonedDateTime convertToZonedDateTime(Date date, ZoneId zoneId) {
    return date.toInstant().atZone(zoneId);
}

public static Date convertToDate(ZonedDateTime zonedDateTime) {
    return Date.from(zonedDateTime.toInstant());
}

Bei der Konvertierung einer Date-Instanz in eine ZoneDateTime muss die entsprechende Zeitzone als ZoneId mitgegeben werden.

Konvertierung der Map von Minecraft 1.12 auf 1.13 durchführen

Vor einigen Wochen erschien Version 1.13 des Open-Word-Spieles Minecraft. Im Zuge dieser Aktualisierung wurden unter anderem die Daten der Blöcke verändert. Beim Erzeugen der Weltkarte über die freie Minecraft-Rendersoftware Mapcrafter traten nach dem Update Probleme auf.

Nur die bereits konvertierten Chunks werden gerendert

Während der Server ohne Probleme lief, wurden in der Karte nur bestimmte Chunks gerendert. Der Grund hierfür war das nur die Chunks in das neue Format der Version 1.13 konvertiert wurden, die von den Spielern auf dem Server besucht worden waren. Alle anderen Chunks lagen noch im Format der Version 1.12 vor. Eine Lösung für dieses Problem schafft der mit 1.13 neu eingeführte Kommandozeilen-Parameter –forceUpgrade des Minecraft-Servers. Wenn man diesen entsprechend startet:

java -Xmx4096M -Xms2048M -jar minecraft_server.jar nogui --forceUpgrade

beginnt der Server alle Chunks in das neue Format zu überführen:

[06:42:34] [Server thread/INFO]: Starting minecraft server version 1.13.1
...
[06:42:34] [Server thread/INFO]: Forcing world upgrade!
[06:42:34] [Server thread/INFO]: Counting chunks...
[06:42:48] [Server thread/INFO]: Upgrading structure data...
[06:42:48] [Server thread/INFO]: 0% completed (0 / 1630135 chunks)...
[06:42:49] [Server thread/INFO]: 0% completed (0 / 1630135 chunks)...
..
[08:52:58] [Server thread/INFO]: 99% completed (1629866 / 1630135 chunks)...
[08:52:59] [Server thread/INFO]: 99% completed (1630017 / 1630135 chunks)...
[08:53:00] [pool-4-thread-1/INFO]: World optimizaton finished after 7812721 ms

Je nach der Größe der eigenen Welt kann dieser Vorgang durchaus einige Stunden in Anspruch nehmen. Nachdem alle Chunks konvertiert wurden, funktioniert das Rendering der Weltkarte wieder wie gewohnt.

OpenDocument-Dokumente nach Markdown konvertieren

Auf der Suche nach einer Möglichkeit mehrere hundert OpenDocument-Dokumente in Markdown zu konvertieren, bin ich schlussendlich bei Pandoc gelandet. Pandoc versteht sich als Konverter um Dokumente schnell und unkompliziert von A nach B zu konvertieren. Um nun eine OpenDocument-Datei in eine Markdown-Datei zu überführen, nutzt man folgende Syntax:

pandoc input.odt -t markdown -o output.md

Neben dieser Konvertierung, bietet Pandoc unzählige weitere Konvertierungen an. Pandoc ist unter der GPL in Version 2 lizenziert und somit freie Software. Verfügbar ist Pandoc für Linux, macOS und Windows.

Daten von KeePassX zu 1Password übertragen

Bei KeePassX und 1Password handelt es sich um Passwortmanager mit welchem man die unterschiedlichsten Passwörter sinnvoll verwalten kann. KeePassX ist dabei eine Mac Variante des freien Passwortmanagers KeePass. Möchte man die Daten von KeePassX zu 1Password importieren, steht man vor dem Problem das die aktuelle Version 2 keine Exportfunktionen unterstützt.

1Password unter Mac OS X

1Password unter Mac OS X

Als Abhilfe kann man KeePass 2 nutzen und die Daten mit diesem in das KeePass XML Format exportieren. Der nächste Schritt besteht darin die entsprechende Konverterapplikation herunterzuladen. Diesen Konverter muss nach dem Download mit der exportieren XML-Datei gefüttert werden:

/usr/bin/perl5.16 convert_to_1p4.pl keepass2 -v /Users/seeseekey/Desktop/passwords.xml

Der Konverter erzeugt im gleichen Ordner eine 1P4_import.1pif-Datei als Ergebnis. Diese wiederum kann in 1Password importiert werden. Der direkte Aufruf der systemeigenen Perl-Installation verhindert das es zu Fehlern wie diesem kommt:

Can't locate Date/Calc.pm in @INC (@INC contains: /opt/local/lib/perl5/site_perl/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/site_perl/5.16.3 /opt/local/lib/perl5/vendor_perl/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/vendor_perl/5.16.3 /opt/local/lib/perl5/5.16.3/darwin-thread-multi-2level /opt/local/lib/perl5/5.16.3 /opt/local/lib/perl5/site_perl /opt/local/lib/perl5/vendor_perl .) at Utils/PIF.pm line 18.

In einem solchen Fall nutzt das System bei Eingabe des Kommandos perl eine alternative Version wie sie z.B. von MacPorts bereitgestellt wird.