Freitag, 26. Oktober 2012
Der gläserne Mensch
Dienstag, 9. Oktober 2012
Enum in Java with array of string values
Creating enums with string values in Java is quite simple. There are many examples for this on the net:
public enum StrEnum {
A ("a"), B ("b"), C ("c");
private final String text;
StrEnum (String text) { this.text = text; }
public String toString () { return text; }
}
Those enums can be used in a switch statement and are printable, because they have a string value.
But sometimes it is useful to have the string values of all enums in a string array. This can be done by the use of ordinal(). The following code adds a static string array with all enum values to the class.
private static final String[] array;
static {
array = new String[StrEnum.values().length];
for (StrEnum value : StrEnum.values())
array[value.ordinal()] = value.toString();
}
public static String[] toArray () { return array; }
And this is the a complete example. Try it with javac scratch.java && java scratch:
class scratch { public enum StrEnum { A ("a"), B ("b"), C ("c"); private final String text; StrEnum (String text) { this.text = text; } public String toString () { return text; } private static final String[] array; static { array = new String[StrEnum.values().length]; for (StrEnum value : StrEnum.values()) array[value.ordinal()] = value.toString(); } public static String[] toArray () { return array; } } public static void main (String[] args) { for (String str : StrEnum.toArray()) { System.out.println (str); } } }
Freitag, 16. Dezember 2011
Compile ucspi-tcp-0.88 on Red Hat Enterprise Linux Client release 5.5 (Tikanga)
Compiling ucspi-tcp version 0.88 on Red Hat ES 5.5 fails with the following error:
./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \
dns.a time.a unix.a byte.a `cat socket.lib`
/usr/bin/ld: errno: TLS definition in /lib/libc.so.6 section .tbss mismatches non-TLS reference in tcpserver.o
/lib/libc.so.6: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [tcpserver] Error 1
The problem is the errno definition in error.h. The problem can be fixed with the following patch:
--- ucspi-tcp-0.88/error.h 2000-03-18 16:18:42.000000000 +0100 +++ ucspi-tcp-0.88.patched/error.h 2011-12-16 09:29:15.000000000 +0100 @@ -1,7 +1,8 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +/* extern int errno; */ +#includeextern int error_intr; extern int error_nomem;
Mittwoch, 30. November 2011
Reading multiple return values with Bashs read function
It is quite easy to read a single return value of a sub process with Bash:
DATE=$(date) echo $DATEThis command spawns a new process and stores the date and displays it. This is easy.
It becomes complicated if one needs the day and month in two different variables. Bashs standard function to parse input is read. So one could think this might be a possible way:
date | read DAY MONTH REST echo $DAY $MONTHBut the above code prints only an empty line. The reason is that the pipe creates a new scope. An equivalent syntax for the above read is this:
date | (
read DAY MONTH REST
)
echo $MONTH $DAY
Now it is obvious why the echo does not print anything. The variables are not valid any more when they get displayed, because the new scope has already been closed. One possible solution is to put the echo into the scope of the sub shell:
date | (
read DAY MONTH REST
echo $MONTH $DAY
)
Now the month and day is correctly displayed. But this solution has a major drawback. The standard input in the sub shell is the standard output of the date command and the original standard input of the surrounding shell gets shadowed and is not available any more in the sub shell.
The solution for this problem is: process substitution. The above command could be written this way using a process substitution:
(
read DAY MONTH REST
echo $MONTH $DAY
) < <(date)
The expression <(date) returns a file descriptor and the output of that file descriptor is redirected to the read block. You can try it with
echo <(date)Which prints the file descriptor and
cat < <(date)which prints the date. But this alone does not help much, because the read is still executed in a sub shell and the variables created by read are in a scope which does not have access to the original standard input. But by using a process substitutions it is possible to avoid the complete sub shell by redirecting the output of date directly into the read.
Normally read reads only from standard input but it is possible to specify a file descriptor by the use of the -u option. Unfortunately Bash uses a different syntax for the file descriptor. The process substitution prefixes the actual file descriptor number with /dev/fd/ while read expects the plain number. But the prefix can be stripped with Bashs parameter expansion functions. The ## operator matches the longest prefix and removes it:
FD=<(date)
echo $FD
echo ${FD##*/}
Combining all this in one line makes it possible to read more than one return value without introducing a new scope and without loosing the current standard input:
FD=<(date) read -u ${FD##*/} DAY MONTH REST
echo $MONTH $DAY
Freitag, 7. Oktober 2011
Bash Promt in Fett
Die folgende Definition der PS1-Variable führt dazu, dass sowohl der Bash-Promt fett gedruckt wird als auch der Titel des Fensters aktualisiert wird.
export PS1='\[\e]0;\u@\h: \w\a\e[1m\]\u@\h:\w\$\[\e[0m\] '
Das ist nützlich, um schnell die Zeile mit der letzten Eingabe erkennen zu können. Andernfalls verschwindet die letzte Eingabe leicht in der Ausgabe der vorherigen Befehle.
Samstag, 10. September 2011
Dateien löschen unter Windows
Unter Unix tippt man einfach "rm -rf müll" und der Müll wird von der Platte entfernt.
Unter Windows ist diese denkbar einfache Aufgabe denkbar kompliziert. Man könnte auf die Idee kommen, das ein einfaches Drücken der Del-Taste im Explorer die Lösung sein könnte: weit gefehlt. Selbst Administratoren können nicht problemlos Dateien löschen. Beispielsweise ist es in bestimmten Situationen notwendig, erst den Besitz von Dateien zu übernehmen, bevor man sie löschen kann. Im Explorer kann das Löschen von Profilen eine Angelegenheit werden, für die man sich ruhig mal eine Auszeit von zwei Wochen gönnen kann. Ist eben alles viel einfacher unter Windows.
Wenn einem dann unter Windows wieder einfällt, dass es ja auch sowas wie eine Kommandozeile gab, ist einem nicht wirklich geholfen. Weder der Versuch mit "del /s /f" noch "rmdir /s /q" führt dazu, dass alle Daten problemlos gelöscht werden.
Aber wenn man lange genug sucht, findet man die Lösung. Man muss ein leeres Verzeichnis erstellen und dieses mit dem Befehl "robocopy" in das zu löschende Verzeichnis spiegeln. Dadurch entstehen zwei leere Verzeichnisse, die einfach mit "rmdir" gelöscht werden können. Das geht dann aber auch wieder im Explorer.
mkdir nix robocopy nix müll /mir /sec rmdir nix rmdir müllIst doch einfacher als "rm -rf" oder?
Montag, 28. Februar 2011
Das fängt ja gut an
Tuess bis demnächst mal, wenn ich wieder Internet habe...
