Zum Inhalt

denniswilmsmann.de Posts

Random File Picker

Mit diesem paar Zeilen Code ist es mit Java 7 möglich, zufällig Dateien aus einer Ordnerstruktur zu kopieren, z.B. um schnell mal 100 mp3 Dateien aus der Sammlung auf eine CD oder einen USB Stick zu schieben, ohne selbst bei der Auswahl Hand kreativ werden zu müssen.

Hier gibts den Sourcecode und ein fertiges JAR File zum Download: RandomFilePicker

/*
* Created on 30.08.2014
*/
package de.denniswilmsmann.rfp;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;

/*
* $Log: $
*/

public class RandomFilePicker {

	private final static List<File> files = new ArrayList<File>();

	public static void main(String[] args) {

		if (args == null || args.length < 4) {
			System.out
					.println("run with java -jar RandomFilePicker.jar <Source Folder> <Destination Folder> <Recursive y/n> <Number of Files>");
			System.out
					.println("run with java -jar RandomFilePicker.jar D:\\MyMusicArchive D:\\RandomMusic y 100");
			return;
		}

		File sourceFolder = new File(args[0]);

		if (!sourceFolder.isDirectory()) {
			System.out.println(args[0] + " is not a folder");
			return;
		}

		File destFolder = new File(args[1]);

		if (!sourceFolder.isDirectory()) {
			System.out.println(args[1] + " is not a folder");
			return;
		}

		boolean recursive = false;
		if (args[2].equalsIgnoreCase("y")) {
			recursive = true;
		}

		int numberOfFiles = Integer.parseInt(args[3]);

		parseFolder(sourceFolder, recursive);

		if (files.size() < numberOfFiles) {
			System.out
					.println("not enough files found, please reduce <Number of Files>");
		} else {
			Set<File> selectedFiles = new HashSet<File>();
			Random generator = new Random();
			while (selectedFiles.size() < numberOfFiles) {
				int i = generator.nextInt(files.size());
				selectedFiles.add(files.get(i));
			}
			for (File f : selectedFiles) {
				File out = new File(destFolder.getAbsolutePath()
						+ File.separator + f.getName());
				try {
					Files.copy(f.toPath(), out.toPath());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	private static void parseFolder(File folder, boolean recursive) {
		for (File f : folder.listFiles()) {
			if (f.isFile()) {
				addFile(f);
			} else if (f.isDirectory() && recursive) {
				parseFolder(f, recursive);
			}
		}
	}

	private static void addFile(File f) {
		// System.out.println(files.size() + 1 + ": " + f.getAbsolutePath());
		files.add(f);
	}
}

Chrome zeigt unter Android weiße bzw. leere Seiten

Seit den letzten ein oder zwei Updates hat Chrome unter Android die dumme Angewohnheit, ab und an weiße bzw. leere Seiten anzuzeigen. Dabei ist es egal, welche Seiten man versucht aufzurufen, denn auch Seiten von Google selbst sind betroffen.

So sieht die leere Seite aus:

chrome-white-page-1

Und so sollte die Seiten eigentlich aussehen:

chrome-white-page-2

Den Cache zu leeren oder sonst irgendwie an den Einstellungen rumzuspielen, hat bei mir keinen Erfolg gebracht. Aber scheinbar bin ich auch nicht ganz alleine mit diesen Problem, wenn man mal einen Blick auch die Chrome Seite im Play Store wirft:

chrome-white-page-3

Kleines Update vom 06.08.2014: Das Problem ist als Bug scheinbar schon seit Februar 2014 bekannt: Issue 342190: OOM conditions killing foreground render process
Scheinbar steht auch ein möglicher Bugfix für die Beta Version in den Startlöchern: https://code.google.com/p/chromium/issues/detail?id=399521#c2

Update vom 25.08.2014: Das letzte Update von Chrome hat das Problem behoben. 🙂

Probleme mit dem Moto G nach dem Update auf Android 4.4.4

Seit einiger Zeit verteilt Motorola das Update auf Android 4.4.4 für das Moto G und auch auf meinem Moto G (alte Version mit 16 GB Speicher) ist es mittlerweile angekommen. Es gibt jetzt ja auch eine Version mit 8 GB Speicher, einem Micro SD Slot und 4G (also LTE), zu der ich wegen der Micro SD nun greifen würden.

Moto G - Android 4.4.4

Aber zurück zum Update: Einen Verbesserung der Leistung oder Laufzeit kann ich nicht feststellen, habe ich aber auch nicht erwartet. Allerdings beenden sich nun deutlich schneller Apps, als vor dem Update. Vor dem Update konnte ich z.B. Musik hören, mit Feedly diverse RSS Feeds browsen und die Artikel dann per Chrome lesen. Nun beendet sich Feedly ab und an, wenn ich den Artikel in Chrome lese. Ist irgendwie ärgerlich, denn dadurch lande ich bei Feedly immer wieder auf dem Home Screen und nicht mehr da, wo ich vorher war.  Kann natürlich auch an Feedly, Chrome oder einer sonstigen App liegen.

Fotos mit Zeitstempel umbenennen

Mit den folgenden paar Zeilen Java Code lassen sich Fotos bequemen umbenennen, d.h. der Dateiname wird noch mit dem Zeitstempel aus den Exif Daten ergänzt. Möglich macht das das Framework metadata-extractor.

/*
 * Created on 28.06.2014
 */
package de.denniswilmsmann.renamephotos;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifSubIFDDirectory;

/*
 * $Log: $
 */
public class RenamePhotos {

  private final DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG);
  private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss");

  public static void main(String[] args) {
    File folder = new File("D:\\PhotosToRename\\");

    RenamePhotos ex = new RenamePhotos();
    ex.parse(folder);
  }

  private void parse(File f) {
    if (f.isDirectory()) {
      parseDirectory(f);
    } else {
      parseFile(f);
    }
  }

  private void parseDirectory(File f) {
    for (File file : f.listFiles()) {
      if (file.isDirectory()) {
        parseDirectory(file);
      } else {
        parseFile(file);
      }
    }
  }

  private void parseFile(File f) {
    try {
      if (f.isFile() && isRenameRequired(f)) {
        Metadata metadata = ImageMetadataReader.readMetadata(f);
        ExifSubIFDDirectory directory = metadata.getDirectory(ExifSubIFDDirectory.class);
        Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);

        String newName = sdf.format(date) + "_" + f.getName();
        System.out.println(f.getName() + " -> " + newName);

        f.renameTo(new File(f.getParent() + "\\" + newName));
      } else {
        System.out.println("skip " + f.getAbsolutePath());
      }
    } catch (ImageProcessingException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    } catch (IOException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    } catch (NullPointerException e) {
      System.out.println("error parsing " + f.getAbsolutePath());
    }
  }

  private boolean isRenameRequired(File f) {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < f.getName().length(); i++) {
      sb.append(f.getName().charAt(i));
      try {
        sdf.parse(sb.toString());
        return false;
      } catch (ParseException e) {
        // ignore
      }

    }
    return true;
  }
}

Und dazu noch die passsende pom.xml, damit die Dependencies einfach via maven geladen werden können:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>RenamePhotos</groupId>
	<artifactId>RenamePhotos</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>com.drewnoakes</groupId>
			<artifactId>metadata-extractor</artifactId>
			<version>2.6.2</version>
		</dependency>
	</dependencies>
</project>

Hier die Dateien vorher:
renamephotos1

Und nachher:
renamephotos2

Die Ausgabe auf der Konsole sieht dazu so aus:

CIMG2773.JPG -> 2012-02-23_172829_CIMG2773.JPG
CIMG2774.JPG -> 2012-02-23_172842_CIMG2774.JPG
CIMG2775.JPG -> 2012-02-23_172847_CIMG2775.JPG
CIMG2776.JPG -> 2012-02-23_172853_CIMG2776.JPG
CIMG2777.JPG -> 2012-02-23_184732_CIMG2777.JPG
CIMG2778.JPG -> 2012-02-23_184746_CIMG2778.JPG
CIMG2779.JPG -> 2012-02-23_184752_CIMG2779.JPG
CIMG2780.JPG -> 2012-02-23_211635_CIMG2780.JPG
CIMG2781.JPG -> 2012-02-23_211646_CIMG2781.JPG
CIMG2782.JPG -> 2012-02-23_211655_CIMG2782.JPG
CIMG2783.JPG -> 2012-02-23_211714_CIMG2783.JPG
CIMG2784.JPG -> 2012-02-23_211724_CIMG2784.JPG
CIMG2785.JPG -> 2012-02-23_211735_CIMG2785.JPG
CIMG2786.JPG -> 2012-02-23_211745_CIMG2786.JPG
CIMG2787.JPG -> 2012-02-23_211801_CIMG2787.JPG
CIMG2788.JPG -> 2012-02-23_211810_CIMG2788.JPG
CIMG2789.JPG -> 2012-02-23_211822_CIMG2789.JPG
error parsing D:\PhotosToRename\desktop.ini

Der Code Style für den eclipse Java Formatter stammt von Google: https://google-styleguide.googlecode.com/svn/trunk/eclipse-java-google-style.xml

Ach ja, es gibt natürlich auch diverse kleine Tools, die das auch alles können, z.B. ExifRenamer für Mac OS oder dieses Tool für Windows.

MP4 Video um 90° rotieren

Mit ffmpeg lassen sich einfach und schnell MP4 Videos im Uhrzeigersinn rotieren, z.B. Handyvideos, die falsch gedreht auf dem PC abgespielt werden:

ffmpeg -i original-video.mp4 -vf "transpose=1" rotiertes_video.mp4

Hinweis: transpose=2 rotiert übrigends gegen den Uhrzeigersinn.

Wiederherstellung von WhatsApp Nachrichten schlägt fehl

Vor einiger Zeit hat WhatsApp angefangen, unter Android die lokale Datenbank auf dem Handy zu verschlüsseln. Das erhöht zwar (etwas) die Sicherheit, erschwert aber leider auch den Umzug alle WhatsApp  Chats auf ein neues Handy. Im Endeffekt liegts am Google Account, mit dem das Android Handy eingerichtet ist. Auf meinem alten Handy war das noch eine @googlemail.com Adresse, auf dem neuen aber eine @gmail.com Adresse. Dadurch hat es nicht gereicht, einfach nur den WhatsApp Ordner vom alten aufs neue Handy zu kopieren. Es kam zwar die Meldung, dass das Backup wiederhergestellt werden konnte, aber ich habe nur meine ganzen Gruppen ohne Inhalt gesehen. Von den restlichen Chats fehlte jede Spur.

Was hat geholfen? Diese Anleitung aus dem Forum von www.android-hilfe.de. Das Tool, was man dazu benötigt, ist hier verlinkt.

Was ich abweichend von der Anleitung machen musste, die mit dem neuen @gmail.com Account verschlüsselte Datei auf dem neuen Handy von msgstore.db.re.crypt5 in msgstore.db.crypt5 umbenennen. Dann konnte ich WhatsApp installieren und das Backup mit ca. 25000 Nachrichten wurde wiederhergestellt.

Screenshot_2014-04-17-22-39-37 Screenshot_2014-04-17-22-40-05

Ach ja, soviel zum Thema Sicherheit & Verschlüsselung von WhatsApp Backups. 😉

AnTuTu Benchmarks: Galaxy Nexus i9250 und Nexus 7 (2012)

Ich spiele mit dem Gedanken, mein altes Galaxy Nexus i9250 in Rente zu schicken und durch ein aktuelleres Modell zu ersetzen. Mein momentaner Favorit ist das Moto G von Motorala. Um grob abschätzen zu können, wie viel mehr Leistung das bringt, habe ich mal meine beiden Geräte mit AnTuTu benchmarken lassen:

Galaxy Nexus i9250

Screenshot_2014-04-12-13-05-52 Screenshot_2014-04-12-13-06-02 Screenshot_2014-04-12-13-06-06

Nexus 7 (2012)

Screenshot_2014-04-12-13-04-12 Screenshot_2014-04-12-13-04-44

Das Moto G liegt bei gut 17.000 Punkten.

MOV Videos in MP4 konvertieren

Hintergrund ist, dass meine Nikon 1 J1 zwar sehr schöne Videos macht, die aber leider recht groß sind. Ich stelle diese z.B. via Google Drive anderen Leuten zur Verfügung. Im Originalformat MOV spielt Google Drive diese leider im Browser nicht ab und die Videos müssen erst runtergeladen werden. Das Problem läßt sich umgehen, indem man das Video in MP4 mit H.264 und einem beliebigen Audio Codec (AAC, OGG, MP3, …) konvertiert, bevor man es in Google Drive ablegt.

Aber wie geht das genau? Ich mache das mit dem Tool HandBrake.

Nach der Installation das Programm starten und mit Source > Open File das Originalvideo öffnen. In meinem Beispiel heißt das DSC_2676.MOV und ist 99,4 MB groß.

1_HandBrake

Bei Destiantion ändere ich noch den Dateinamen von M4V in MP4 und passe den Pfad an, wo das neu kodierte Video dann landen soll.

2_HandBrake

Auf den Tabs Video und Audio können jetzt bei Bedarf noch Änderungen gemacht werden. Ich lasse das aber einfach mal so.

3_HandBrake

 

4_HandBrake

 

Jetzt nur noch auf Start klicken und warten. Je nach Leistung des PCs und der Größe des Videos kann die Kodierung schon mal einige Minuten dauern. Das Resultat ist in meinem Beispiel eine Datei Dsc 2676-1.mp4 die nur noch 21,6 groß ist und direkt von Google Drive im Browser abgespielt werden kann.

Plesk 502 Bad Gateway

Wer beim Login in Plesk einen Fehlermeldung à la „502 Bad Gateway“ erhält, kann einen Blick in das Logfile /var/log/sw-cp-server/error_log werfen um ein paar mehr Details zu bekommen:

2014/04/10 19:14:48 [crit] 1077#0: *7 connect() to unix:/var/run/sw-engine.sock failed (13: Permission denied) while connecting to upstream, client: 37.201.xxx.xxx, server: , request: "GET /login_up.php3 HTTP/1.1", upstream: "fastcgi://unix:/var/run/sw-engine.sock:", host: "mein-vserver.de:8443"
2014/04/10 19:14:53 [crit] 1077#0: *7 connect() to unix:/var/run/sw-engine.sock failed (13: Permission denied) while connecting to upstream, client: 37.201.xxx.xxx, server: , request: "GET /login_up.php3 HTTP/1.1", upstream: "fastcgi://unix:/var/run/sw-engine.sock:", host: "mein-vserver.de:8443"
2014/04/10 19:15:24 [crit] 1077#0: *7 connect() to unix:/var/run/sw-engine.sock failed (13: Permission denied) while connecting to upstream, client: 37.201.xxx.xxx, server: , request: "GET /login_up.php3 HTTP/1.1", upstream: "fastcgi://unix:/var/run/sw-engine.sock:", host: "mein-vserver.de:8443"
2014/04/10 19:15:27 [crit] 1077#0: *7 connect() to unix:/var/run/sw-engine.sock failed (13: Permission denied) while connecting to upstream, client: 37.201.xxx.xxx, server: , request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/sw-engine.sock:", host: "mein-vserver.de:8443"

Bei mir hat dann ein Neustart von Plesk geholfen: /etc/init.d/sw-cp-server restart