Silbentrennung – im Web!

Geschrieben von Andi

*staub wegpust*

Hallo! :D

Heute will ich mit euch mal eine Entdeckung teilen, die ich gestern gemacht habe. Und zwar eine ziemlich geniale, wie ich finde. Wie der Titel schon sagt: Es geht um Silbentrennung in Webseiten. Und zwar um automatische Silbentrennung! Die Hervorhebung deshalb, weil es zuvor schon möglich war, eine Silbentrennung in Webseiten umzusetzen, hier aber jede menge manuelle Arbeit von nöten war. Man musste nämlich das sogenannte Soft Hyphen-Zeichen überall dort einfügen, wo ein Umbruch erlaubt sein sollte. Was natürlich mit entsprechendem Aufwand verbunden ist, wenn man in einem längeren Fließtext bei allen Wörtern die entsprechenden Trennungsregeln umsetzen wollte.
Diese Zeiten sind jetzt dank dem Hyphenator von Mathias Nater vorbei! :) Der Hyphenator ist in JavaScript programmiert und setzt zur automatischen Ermittlung der Trennungsstellen den Algorithmus von Franklin M. Liang um.

Es gibt zudem eine PHP-Lösung, die auf dem Hyphenator basiert. Für die, die ihre Texte aus Performancegründen auf dem Server verarbeiten möchten: phpHyphenator
Ein WordPress-Plugin ist ebenfalls verfügbar, das ich kurzerhand hier auf coffee() break; verbaut habe: Hyphenator für WordPress

Hoffe ihr habt viel Freude mit dem Hyphenator! :)

Resharper 5: Verlängerte 60-Tage-Testlizenz + 10% Rabatt auf Lizenzerwerb

Geschrieben von Andi

Hallo, ich komm gleich zur Sache: Resharper ist cool. Wer das noch nicht weiß, sollte sich unbedingt einmal die Testversion des Visual-Studio-Addins herunterladen und einfach mal ausprobieren.

Das blöde für Hobby-Programmierer (bzw. für Entwickler die auch nebenberuflich programmieren, aber nicht unbedingt komerziell) ist allerdings, dass Resharper auch nicht ganz billig ist. Eine Personal Licence kostet immerhin 188 €. Wer also das Addin noch etwas länger testen möchte, der kann einen kostenlosen 60-Tage-Testlizenzschlüssel erhalten.
Dazu muss man einfach eine Anfrage an David Ridgway (Details siehe Blog) stellen und man erhält per E-Mail einen persönlichen Lizenzschlüssel und zusätzlich noch einen 10%-Rabatt-Code, falls man sich dazu entschließt, Resharper anschließend zu kaufen. Finde ich persönlich eine prima Sache! :)

P.S.: Wer ganz schlau ist, reizt erst die Standard-30-Tage-Testversion von Resharper 5 aus und gibt anschließend den 60-Tage-Lizenzschlüssel ein. So schafft man es immer hin auf 90 Tage Testzeitraum. ;)

Update vom 03.06.2010: Das Angebot von Jetbrains ist leider nicht mehr gültig. :(

Exe Joiner – Schwurbel

Geschrieben von Michael

Mahlzeit!

Das Java-Tool Schwurbel erlaubt das packen von mehreren Dateien zu einer einzelnen Exe.

Features:

  • Icon kann festgelegt werden
  • Dateien können direkt nach dem Auspacken ausgeführt werden
  • Dateien können an festgelegte Pfade oder in das Verzeichnis der Exe entpackt werden
  • Mit etwa 20kb ein sehr kleiner Overhead

Schwurbel – Source und Jar


|Den ganzen Beitrag lesen…

sendtoftp rewritten

Geschrieben von Michael

Tach!

Ich habe mir mal die Mühe gemacht sendtoftp vollkommen neu zu schreiben. Diesmal allerdings nicht in Java, sondern in Gentee. Das Ergebnis ist erstaunlicherweise (ich lerne gentee seit 3 Wochen) annehmbar. Die Geschwindigkeit ist rapide angestiegen und die Größe von 72kb ist auch beeindruckend. Die Fehler aus der Java-Version habe ich nun auch gefixt:

  • Linkgenerierung hat fehlerhafte Links produziert
  • Pfade mit Leerzeichen haben teilweise Probleme verursacht
  • Die Konfiguration ist ein klein wenig umgestaltet:

    [general]
    # ip or dns of the ftp server
    host=localhost
    # username for the login
    username=anonymous
    # password for the login
    password=anonymous
    [link]
    # to be added before the path to the file
    prefix=http://
    # if you want to remove pieces of the links to the files
    badprefix=/htdocs
    [remote]
    # the directory where the files will be uploaded to (relative to the root)
    ftpdir=/htdocs/uploads
    

    Neu ist der Parameter “badprefix” welcher besagt das Teile des Pfades zu den Dateien entfernt werden sollen. Beispielsweise um Links zu generieren welche vom Internet aus erreichbar sind. Auch neu ist “prefix”, was einfach das protokoll darstellt, welches den Links vorne angehängt werden soll.

    sendtoftp Installer1.0G – 66,3 KB
    sendtoftp 1.0G Source – 56,8 KB

DelegateBinder – DataBinding mit Datenmanipulation

Geschrieben von Andi

Ich hatte mal irgendwann vor längerer Zeit die Idee, eine Klasse zu programmieren, mit der ich einfache GUI-Logik leicht implementieren kann, ohne unnötigen Code schreiben zu müssen. Ziel war es, Dinge wie z.B. “Aktiviere einen Button nur, wenn eine gültige/vorhandene Datei in einer TextBox eingegeben wurde” oder “Deaktiviere andere Controls, wenn eine CheckBox angehakt ist” und sonstige kleine Spielereien die man dann und wann in der GUI-Programmierung braucht, zu vereinfachen.
Bisher musste ich sowas immer auf die Weise erledigen, dass ich (im Falle des ersten Beispiels) eine Methode programmiert habe, die über die File.Exists-Methode geprüft hat, ob der String in der TextBox auf eine gültige Datei verweist. Anschließend musste ich das TextChanged-Ereignis an die Methode hängen, damit die Prüfung erneut ausgeführt wird, wenn der Benutzer den Text ändert. Das funktioniert zwar und ist nicht allzu schwer in der Umsetzung, der Designer nimmt einem den nervigen Event-Kram ja ab, aber was ich bei dieser Lösung unschön finde, ist, für einen Einzeiler extra eine Methode schreiben zu müssen. Also hab ich mich hingesetzt und mir eine Lösung überlegt, und rausgekommen ist der DelegateBinder.

Vorab schon einmal der C#-Code der Klasse:

using System;
using System.ComponentModel;
using System.Windows.Forms;

[ToolboxItem(false)]
public class DelegateBinder : Control
{
    public delegate object BindingDelegate(object value);

    private BindingDelegate _bindingDelegate;
    private object _bindingProperty;

    public object BindingProperty
    {
        get { return _bindingProperty; }
        set { _bindingProperty = _bindingDelegate(value); }
    }

    private DelegateBinder(BindingDelegate bindingDelegate)
    {
        _bindingDelegate = bindingDelegate;
    }

    public static void Bind(BindingDelegate bindingDelegate, Control target, string propertyName, object dataSource, string dataMember)
    {
        if (bindingDelegate == null)
            throw new ArgumentNullException("bindingDelegate");

        if (target == null)
            throw new ArgumentNullException("target");

        if (dataSource == null)
            throw new ArgumentNullException("dataSource");

        var binder = new DelegateBinder(bindingDelegate);
        target.Controls.Add(binder);
        binder.DataBindings.Add("BindingProperty", dataSource, dataMember);
        target.DataBindings.Add(propertyName, binder, "BindingProperty");
    }
}

Funktionsweise
Die Klasse DelegateBinder hat eine statische Methode Bind, die als Parameter einen Delegaten – der einen Object-Parameter erwartet und ein Object zurückgibt – und eine Referenz auf das Zielobjekt (das Control, dem das Binding hinzugefügt werden soll) empfängt. Weiterhin übergibt man der Bind-Methode wie beim normalen DataBinding-Konstruktor die Parameter für propertyName, dataSource und dataMember.
Der Trick bei dieser ganzen Sache ist nun folgender: In der Bind-Methode wird ein neues DelegateBinder-Objekt erzeugt. Das Objekt hat eine Eigenschaft BindingProperty, an welche ich den Member der DataSource (also die Eigenschaft des Objekts, von dem die Daten kommen) binde. Nun dreh ich den Spieß um und binde die BindingProperty dieses Objekts an das Ziel-Objekt, das die (veränderten) Daten enthält. Das eigentliche Konvertieren/Bearbeiten der Daten erfolgt durch den Delegaten, den man der Bind-Methode übergibt. Dieser wird im Setter der BindingProperty aufgerufen, also immer dann, wenn sich die Daten vom Control (oder welches Objekt auch immer) geändert haben. In dem Moment, in dem nun der Wert der Eigenschaft BindingProperty geändert wird, schlägt das DataBinding des eigentlichen Ziel-Controls/Objekts zu, das ja an das DelegateBinder-Objekt gebunden ist und erhält den nun geänderten Wert. Die eigentliche Datenmanipulation findet daher über den “Zwischenmann” statt, der zwischen der DataSource und dem eigentlichen Target zwischengeschaltet ist.

Anwendung
Die Beispiele von oben würde man folgendermaßen umsetzen:

DelegateBinder.Bind(x => File.Exists((string)x), button1, "Enabled", textBox1, "Text");
DelegateBinder.Bind(x => !(bool)x, textBox2, "Enabled", checkBox1, "Checked");
DelegateBinder.Bind(x => !(bool)x, listView1, "Enabled", checkBox1, "Checked");

Im angehängten Beispielprojekt sieht man das ganze in einem WinForms-Projekt in Aktion.

DelegateBinderSampleProject

Disposable TemporaryFile

Geschrieben von Andi

Wenn man in einem Programm mit temporären Dateien arbeitet, gehört es normalerweise zum guten Ton, diese anschließend wieder aus dem Temp-Verzeichnis des Benutzers zu löschen, um die Festplatte nicht zuzumüllen.
Das ist natürlich in einem gewissen Grad für den Programmierer nervig. Als ich einen entsprechenden Anwendungfall hatte, habe ich mir gedacht, das muss auch irgendwie eleganter und einfacher gehen. Das hat mich schließlich auf die Idee gebracht, eine kleine Klasse zu programmieren, die mir den ganzen Nebenkram des Dateihandlings – erstellen und wieder löschen der physikalischen Datei – abnimmt. Hierfür hat sich das Dispose Pattern angeboten, das man in .NET über das IDisposable-Interface implementieren kann.

Herausgekommen ist eine kleine aber feine Klasse:

using System;
using System.IO;

public sealed class TemporaryFile : IDisposable
{
    private bool disposed;

    public string FilePath { get; private set; }

    public TemporaryFile()
    {
        FilePath = Path.GetTempFileName();
    }

    ~TemporaryFile()
    {
        Dispose(false);
    }

    #region Dispose Pattern Implementation

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (File.Exists(FilePath))
            File.Delete(FilePath);

        disposed = true;
    }

    #endregion
}

Jetzt ist es ganz bequem möglich, eine temporäre Datei in einem using-Block zu verwenden. Sobald das Ende des Codeblocks erreicht ist, wird die Datei automatisch wieder gelöscht:

using (var file1 = new TemporaryFile())
{
    Console.WriteLine(file1.FilePath);
    // Sonstige Arbeiten an der temporären Datei
}

SendToFtp

Geschrieben von Michael

Das Tool SendToFtp ermöglicht das Uploaden von Dateien auf einen Ftp-Server. Das Besondere ist, dass der Upload über das “Senden An” – Kontextmenü angestoßen wird. Dies ermöglicht eine bequeme Auswahl über den Windows-Explorer.

Nach dem Upload befinden sich dann Direktlinks zu den Dateien in der Zwischenablage. Dadurch ist das Tool besonders dafür geeignet einem Chatpartner eine Datei bereitzustellen ohne dies über die (meist überlasteten/langsamen) Server des Chatprotokolls abwickeln zu lassen.

Die Konfiguration des Tools besteht aus einer kleinen property file. Dort kann außerdem ein Proxy eingestellt werden.
Nachfolgend kurz eine Beispielkonfiguration:

; the hostname of the ftp server
ftp.hostname=ftp.server.de
; the port of the ftp server, default is 21
ftp.port=21
; the username for the login, default is anonymous
ftp.username=horst
; the password for the login, default is anonymous
ftp.password=geheimespasswort
; the directory where the files will be uploaded to
ftp.working.directory=horst/uploads/sendtoftp
; If you connect via a proxy
ftp.proxy.host=192.168.202.1
ftp.proxy.port=4568

Version 1.1
Neue Features:

  • Hochladen von kompletten Verzeichnissen mitsamt den enthaltenen Dateien
  • Option ein Verzeichnis auf dem FTP-Server auswählen zu können in welches die Dateien hochgeladen werden
  • Wesentlich geringere Größe durch die Nutzung der abgespeckten FTP Commons Net Library

SendToFtp Installer – 1.1 – 122 KB
SendToFtp Source 1.1 – 89 KB

RandomVideoChooser

Geschrieben von Michael

Wer war nicht schon mal Abends dagesessen und hat sich gedacht: “Ein Film gucken könnte ich! Nur welchen?”.
Da dieses Problem regelmäßig bei mir auftritt habe ich nun mit einem kleinen Progrämmchen für Abhilfe gesorgt.

Mit dem Javatool RandomVideoChooser wird ein Film per Zufall ausgewählt und mit dem Lieblings-Videoplayer zum Abspielen gebracht.

Das Programm sucht im ersten Schritt alle Dateien aus einem Verzeichnis welches der Benutzer via Konfigurationsdatei einstellen kann. Die relativen Pfade vom Verzeichnis zu den Videos werden in eine Datei gespeichert, auch Index-datei genannt. Diesen Schritt übernimmt eine kleine Batchdatei oder ein Shellskript welches eine Funktion in der Jar aufruft.

Der zweite Schritt besteht dann darin die Datei mit den relativen Pfaden auszulesen, per Zufall eine Datei auszuwählen und diese Datei mit dem Videoplayer anzuzeigen. Dieser Schritt kann ebenfalls durch eine Batch oder ein Shellskript getriggert werden, ich habe mich allerdings dafür entschieden es per Manifest zu erledigen. Ein Doppelklick auf die Jar reicht also aus.

Die Idee das Programm in zwei Teile aufzuteilen kam daher, dass das Programm unter Windows verhältnismäßig lange dafür braucht das Verzeichnis nach Videodateien zu durchsuchen.
Ich habe allerdings auch nicht näher nachgeforscht was genau den Vorgang verlangsamt.

Ein weiterer Vorteil dieser Vorgehensweise ist, dass man bereits gesehene Filme aus der Auswahl ausschliessen kann. Um das zu tun muss man dem Eintrag der Filmdatei in der Index-datei eine Raute (#) voranstellen.

Das Programm ist Beerware

RandomVideoChooser Source sowie compiliertes Programm – 21,5 KB

Des Kaffees Pause

Geschrieben von Andi

Frei nach: Des Pudels Kern. Haha! Ha. Ha…

So, nach dieser überaus lustigen Einleitung will ich erstmal erklären, was das hier alles soll. Also. Im Grunde gar nichts. Das hier ist nur ein weiterer Blog, der seinen Platz in den Tiefen dieses Internet-Universums einnehmen wird.

Und zwar gehört dieser Blog Michael und Andi (das bin ich!). Wir sind zwei Fachinformatiker / Anwendungsentwickler in Ausbildung, die wir glücklicherweise bald beenden werden.
Entstanden ist der Blog, nachdem mich Michael fragte, ob ich denn einen Blog hätte und ich darauf hin meinte, dass ich zwar schon gerne bloggen würde, mich aber nie dazu aufraffen könne, endlich ein Blogsystem aufzusetzen und einzurichten. Da hatte er mich dann gefragt, ob ich denn nicht mit ihm zusammen einen Gemeinschaftsblog machen möchte. Ich fand die Idee gar nicht so schlecht, unter der Bedingung, dass er das ganze System einrichtet. :D
Lange Rede kurzer Sinn: Jetzt haben wir diesen Blog, in dem jeder von uns in unregelmäßigen Zeitabständen irgendwelche (belanglosen) Blogeinträge posten wird. Voraussichtlich wird sich hier das meiste um die Themen Programmierung und allgemeine Computer-Technik drehen. So wird es jedenfalls meinerseits sein. Also, nur damit ihr schonmal in etwa wisst, was euch hier erwartet… :)

Eine kurze Erklärung noch zum Blogtitel: Da wir beide Informatiker sind, sind wir nicht wirklich für unsere kreativen Einfälle bekannt. Daher gestaltete sich die Titelsuche sehr demotivierend. Nachdem Michael zuerst den unverbindlichen Vorschlag Freak und Geekiger machte (in Anspielung auf Dumm und dümmer) und ich von diesem nicht sehr begeistert war, meinte er, irgendetwas mit Kaffee wäre cool. Ich gestand dann ehrlich, dass von Anfang an mein erster Gedanke Kaffeepause war. Denn Informatiker sind ja bekannt dafür, Kaffeejunkies zu sein. Nicht umsonst gibt es den Spruch A programmer is just a tool which converts caffeine into code. Allerdings fand ich den Titel langweilig. Trotzdem hab ich die Idee dann etwas weiterverfolgt und war dann schnell bei der englischen Version coffee break. Da mich das break an die Anweisung zum verlassen eines Codeblocks oder einer Switchanweisung in einigen Programmiersprachen wie z.B. C#, C++ und Java erinnerte, entstand dann der Titel coffee() break;, um somit auf die programmierlastigkeit des Blogs anzuspielen. Im übrigen mag ich keinen Kaffee.

Nach dieser überaus unterhaltsamen Anekdote ist jetzt hoffentlich niemand eingeschlafen. :yawn:

Wir wünschen euch noch viel Spaß hier. :)