Gefällt dir dieser Artikel?

Java: falsche Zeitstempel in Dateinamen korrigieren

erschienen in der Kategorie Software, am 27.07.2014
Schnatterente
Ich wurde kürzlich mit dem folgenden Problem konfrontiert:
Ein Bekannter von mir betreibt zwei Webcams, welche alle 5 Minuten Bilder auf einen FTP-Server hochladen. Jetzt wurde für die vielen Fotos ein Webcam-Viewer entwickelt, der es erlaubt alle Bilder auf seiner Webseite einzusehen. Dabei fiel auf, dass die Kameras die bisherigen Bilder (einige Tausend Stück) falsch benannt haben.

Die Dateinamen der Fotos beinhalten immer auch den Zeitstempel, zu dem diese aufgenommen wurden. Weil in den Kameras aber falsche Uhrzeiten und Zeitzonen eingetragen waren, stimmten die Angaben nicht, was auch dazu führte, dass der Webcam-Viewer auf der Webseite seltsame Dinge anzeigte. Wenn es (im Sommer in Hamburg) nachts um 3 schon hell und abends um 7 Uhr schon dunkel ist, kann etwas nicht stimmen. Im konkreten Fall gab es eine zeitliche Verschiebung von vier Stunden und das fällt dem Webseitenbesucher dann schnell auf.

Das Problem mit den falschen Zeitstempeln ließ sich natürlich dadurch beheben, dass wir die Kamera-Einstellungen entsprechend angepasst haben. Da aber auch die bisherigen Bilder online bleiben sollten, musste eine Lösung zur Korrektur der Dateinamen her.
Ich habe dann ein kleines Java-Programm geschrieben, dass die (in unserem Fall rund 8.000) Bilder automatisch anhand eines Zeit-Offsets umbenennt.

Da ich mir vorstellen kann, dass vielleicht noch mal irgendwer in die Verlegenheit kommt, irgendwelche Zeitstempel korrigieren zu müssen, stelle ich den Quelltext hier zur Verfügung:


import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Zeitstempelkorrektur {
  // Konfiguration
  private static int offsethours = -4; // Verschiebung in Stunden
  private static int prefixlength = 7; // Prefix im Dateinamen
  private static int postfixlength = 4; // Postfix im Dateinamen
  private static String tsformat = "yyyyMMdd_HHmmss"; // Zeitstempel-Format

  private static File inputFolder = new File("input"); // Quellverzeichnis
  private static File outputFolder = new File("output"); // Zielverzeichnis

  public static void main(String[] args) {

    if (inputFolder.getAbsolutePath().toLowerCase()
        .equals(outputFolder.getAbsolutePath().toLowerCase())) {
      System.out.println(
        "Fehler: Ein- und Ausgabepfad unterschiedlich sein.");
    } else {
      File[] input = inputFolder.listFiles();

      for (File f : input) {
        String filename = f.getName();
        System.out.println("IN: " + filename);
        String prefix = filename.substring(0, prefixlength);
        String postfix = filename.substring(filename.length()
            - postfixlength, filename.length());
        filename = filename.substring(prefixlength);
        filename = filename.substring(0, filename.length()
            - postfixlength);

        SimpleDateFormat sdf = new SimpleDateFormat(tsformat);
        try {
          Date date = sdf.parse(filename);
          Calendar cal = Calendar.getInstance();
          cal.setTime(date);
          cal.add(Calendar.HOUR_OF_DAY, offsethours);

          String outname = prefix + sdf.format(cal.getTime()) + postfix;

          System.out.println("OUT: " + outname);
          f.renameTo(new File(
            outputFolder.getAbsolutePath()+File.separator+outname));

        } catch (Exception ex) {
          ex.printStackTrace();
        }
      }
    }
  }
}


Der Code ist in dieser Form für die Dateinamen ausgelegt, mit denen wir es zu tun hatten. Ein Webcam-Bild hieß zum Beispiel: "03113A_20140619_100454.jpg". Die Präfixlänge oben im Code dient zur Eliminierung des Substrings "03113A_" (7 Zeichen). Wer Dateien umbenennen will, in deren Namen kein Präfix vorkommt, kann den Wert einfach auf 0 setzen. Mit dem Postfix (in diesem Fall ".jpg", also 4 Zeichen) verhält es sich genau so. Übrig bleibt der Zeitstempel "20140619_100454", welcher offensichtlich das Format "yyyyMMdd_HHmmss" aufweist.
Im Ordner "input" liegen die Quelldateien mit den falschen Dateinamen. Sie werden in das Verzeichnis "output" verschoben und dabei umbenannt. (Das heißt, wenn das Programm fertig ist, sollte der "input-Ordner leer sein.)

Viel mehr gibt es zu den paar Zeilen eigentlich nicht zu sagen. Wer statt einem Stunden-Offset eher Sekunden, Minuten oder Tage braucht, kann den Code natürlich entsprechend verändern (siehe hier). Information zum Zeitstempel-Format gibt es hier.

Noch ein Tipp für Java-Anfänger: Im Zusammenhang mit der Dateinamenkorrektur könnten auch die String-Funktionen trim(), toLowerCase() und toUpperCase() nützlich sein.


Bei Fragen einfach Kommentieren. :)

Geschnatter

4 Kommentare, selbst mitschnattern << < Seite 1/1 > >>
Ulli, am 27.07.2014 um 18:53 Uhr
Die Datei-Zeitstempel (Erstellt/geändert) kann man zumindest bei Windows ohne Software korrigieren. Dies erreicht man, indem man das Dateisystem FAT und NTFS gegeneinander ausspielt. NTFS speichert die Zeiten in UTC, FAT nimmt immer die Ortszeit. Angenommen ich habe auf meinem FAT(32) formatierten Stick ein Foto von 12:00Uhr. Ich kopiere es auf eine NTFS-Partition. Intern wird 10:00 Weltzeit vermerkt, zur Anzeige in MESZ werden zwei Stunden dazugepackt. Dann stelle ich meinen Rechner auf englische Zeitzone um und alle Zeiten springen eine Stunde zurück. Dann die Datei wieder rüber auf den Stick. Das Foto auf dem Stick ist dann von 11:00. Daran ändert sich auch nichts wenn man danach die Zeitzone wieder korrigiert.
Für vier Stunden müßte man vorübergehend irgendwo nach Asien umziehen.
Dann gibt es sicherlich Möglichkeiten aus den Zeitstempeln Dateinamen zu bauen.
Tobias, am 27.07.2014 um 19:59 Uhr
@Ulli: Soweit ich das hier verstehe geht's hier nur um Dateinamen, bzw. Zeitstempel die in Dateinamen geschrieben wurden (nicht um die Zeitstempel der Dateien selbst).
Antwort: Das ist korrekt, was Ulli geschrieben hat ist aber dennoch sehr interessant. :)
Harald, am 29.07.2014 um 14:08 Uhr
Danke fürs Teilen!
PBB, am 26.09.2014 um 14:46 Uhr
DAS hat mir grad den Ar*** gerettet. SPITZE!