2__12.rtfd -- /usr/axel/vorl/java97/skript/skript

Werbung
81
Copyright 1996-1997 by Axel T. Schreiner. All Rights Reserved.
Information über Dateien — main/Ls
Ls informiert über den aktuellen Katalog oder über die Pfade, die als Argumente angegeben
sind. Mit der Flagge -l wird möglichst viel Information ausgegeben. Mit der Flagge -d wird
Information über einen Katalog statt über seinen Inhalt ausgegeben. Nachrangig dazu wird mit
der Flagge -R ein Katalog rekursiv traversiert.
Ls ist eine einfache Version des UNIX-Kommandos ls und illustriert einige der Möglichkeiten,
die die Klasse File
zur Umgang mit Dateien bietet.
ist deutlich so konzipiert, daß nur portable Informationen verfügbar sind. Leider hat die
Klasse unter Windows leichte Probleme mit Platten. Unter UNIX kann man symbolische Links
nicht erkennen, was Ls gefährlich macht.
File
Für Ls gibt es keine Randbedingungen, folglich kann die Klasse von MainClient abstammen.
Wie üblich werden die Flaggen notiert — da es nur ein Klienten-Objekt gibt, genügen
Instanzvariablen.
{programs/main/Ls.java}
import java.io.*;
import lib.main.*;
/** A client class to implement a simple ’ls’ command */
public class Ls extends MainClient {
public static void main (String args []) {
Main main = new Main(new Ls());
try {
System.exit(main.run(args));
} catch (IllegalArgumentException e) {
System.err.println("usage: "+main.name+" [-dlR] path...");
} catch (Exception e) {
main.error(e);
}
System.exit(1);
}
/** record flags */
public boolean dflag, lflag, Rflag;
public boolean flag (char ch, Main m) throws IOException {
switch (ch) {
case ’d’:
dflag = true; return true;
case ’l’:
lflag = true; return true;
case ’R’:
Rflag = true; return true;
default:
return super.flag(ch, m);
}
}
{}
82
Die Argumente kann man an eine zentrale Funktion ls(dirname, path) weiterleiten:
{programs/main/Ls.java}
/** no argument -- process current directory */
public int arg (Main m) throws IOException {
ls("", System.getProperties().getProperty("user.dir", "."));
return 0;
}
/** argument -- process a path */
public int arg (String arg, Main m) throws IOException {
ls(arg == null || arg.equals(".") ? "" : arg+File.separator, arg);
return 0;
}
{}
Man kann eigentlich nicht davon ausgehen, daß der Name . überall auf den aktuellen Katalog
verweist. Mit der System-Property user.dir kann man den aktuellen Katalog feststellen.
Zur Verschönerung der Ausgabe übergibt man den Katalog-Präfix separat vom kompletten
Pfad.
liefert bei toString() nur einen Pfad . Zum Ersatz unter Kontrolle einer Flagge dient
eine Komponentenklasse. Da sie in Blöcken verwendet wird, kann sie nicht lokal in ls() sein:
File
{programs/main/Ls.java}
/** A class to produce information about a path */
protected class File extends java.io.File {
/** constructs, even if path does not exist */
public File (String path) { super(path); }
/** provides a directory listing */
public String toString () {
StringBuffer s = new StringBuffer();
if (lflag) {
if (isDirectory())
s.append("d");
else if (isFile())
s.append("-");
else
s.append("?");
s.append(canRead() ? "r" : "-")
.append(canWrite() ? "w" : "-")
.append("\t" + length() + "\t");
}
return s.append(getPath()).toString();
}
}
{}
83
File hilft dadurch bei der Traverse eines Katalogs, daß die einfachen Dateinamen (ohne . und
..) mit der Methode list()
als Vektor geliefert werden:
{programs/main/Ls.java}
/** take care of one file */
protected void ls (String dirname, String path) {
File f = new File(path);
if (! f.exists())
System.err.println(path + ": does not exist");
else if (! dflag && f.isDirectory()) {
String names [] = f.list();
if (names == null)
// can still happen: Windows 95
names = new File(path + ".").list();
// kludge...
File files [] = new File [names.length];
for (int n = 0; n < names.length; ++ n)
files[n] = new File(dirname + names[n]);
for (int n = 0; n < files.length; ++ n)
System.out.println(files[n]);
if (Rflag)
for (int n = 0; n < files.length; ++ n)
if (files[n].isDirectory())
ls(dirname+names[n]+File.separator, files[n].getPath());
} else
System.out.println(f);
}
}
{}
File.separator ist eine Klassenvariable , mit der der lokale Komponententrenner portabel
gehalten wird. Es gibt ihn auch als System-Property. Die Lösung geht von homogenen Pfaden
aus, die zum Beispiel bei Windows nicht vorliegen.
Leider ist die Windows-Implementierung von File reichlich defekt in bezug auf die Wurzel
eines Laufwerks. Ohne die obige ‘‘Korrektur’’ erhält man folgendes:
c> java Ls c:
c:
c> java Ls c:\
Ls: java.lang.NullPointerException
c> java Ls \
Ls: java.lang.NullPointerException
C> java Ls c:\.
Nur der letzte Versuch funktioniert. Man kann zwar das vorliegende Beispiel reparieren, aber
eigentlich sollte man auf Korrektur der Klasse drängen.
Die Reparatur korrigiert nicht das Problem, daß man für unlesbare Kataloge unter UNIX
offenbar auch null erhält.
Herunterladen