![]() |
Filter.exe |
|
Neulich wollte ich mir eine schöne MP3-CD brennen. Einen Pool an MP3-Titeln habe ich auf meiner Festplatte. Und eine "Playlist" mit den schönsten Titeln hatte ich auch schon. Kein Problem - mit FOR /F "eol= tokens=*" %%i in (Playlist.m3u) do copy "%%i" "c:\meineCD\%%~nxi" kopiere ich mir die Dateien zusammen und brenne sie mir dann auf CD - habe ich gedacht. Falsch gedacht. Die Syntax des FOR-Befehles ist durchaus richtig und funktioniert (zu mindest unter Windows NT, -2000, -XP). Nach einiger Tüftelei, hatte ich die Ursache gefunden. Am Ende jeder Zeile der Playlist.m3u stand ein unsichtbares 0-Byte. Damit kann Windows nicht umgehen. Auch mit dem Copy-Befehl im ASCII-Modus, waren die Nullen nicht weg zu bekommen. Vielleicht gibt es ja sogar einen Weg, um dieses Problem mit Windows-Mitteln zu bezwingen. Aber was macht man, wenn man selber programmieren kann, man schreibt sich ein kleines Tool. Schnell etwas zusammen stricken, für dieses spezielle Problem? Nein - universell, ein paar zusätzliche Funktionen, wieder verwendbar und ziemlich perfekt sollte es schon sein. Und so entstand eben dieses Kommandozeilenprogramm. Es kann beim Kopieren einer Datei Bytes entfernen/ ersetzen, Großbuchstaben in Kleinbuchstaben ändern und umgekehrt. Wie das genau geht, erfährt man durch die Eingabe filter /help oder filter /? (siehe Bild unten). Ich hoffe, es gibt irgendjemanden, der dieses Programm zu irgendeinem Zweck einmal nutzbringend einsetzen kann. |
program filter;
{$APPTYPE CONSOLE}
uses
SysUtils;
Type TError=(EKeinFehler,
EHilfe,
ESyntaxfehler,EParameteranzahl,
ELesefehler,ESchreibfehler);
var
Quelle, Ziel: file;
NumRead, NumWritten: Integer;
Buf: array[1..2048] of Byte;
Ersatzcode:array[0..255] of byte;
ZuFiltern,ZuErsetzen: array[0..255] of boolean;
n,m,o,code,b1,b2,counter:integer;
error:TError;
temp,temp2,temp3:string;
CopyEnd:boolean;
optlowcase,optupcase,optNoInfo:boolean;
begin
error:=EKeinFehler;
for n:=0 to 255 do begin
ZuFiltern[n]:=false;ZuErsetzen[n]:=false;
end;
if (paramcount>0)then begin // Hilfe?
temp:=lowercase(paramstr(1));
if (pos('/?',temp)=1)or(pos('/help',temp)=1) then error:=EHilfe;
end;
if error=EHilfe then begin // ############### HILFE ################
write(#13+#10+
' ## filter.exe ## (Freeware by H.Reither 27.6.2004'+#13+#10+
' Mail: H.Reither@web.de)'+#13+#10+
'Kommandozeile:'+#13+#10+
' filter /help (zeigt diese Hilfe)'+#13+#10+
' filter Quelldatei Zieldatei [/BQuelle[:Ziel]] ... [/BQuelle[:Ziel]] [/UCase] [/LCase] [/NoInfo]'+#13+#10+
''+#13+#10+
' "filter.exe" liest die Quelldatei Byteweise, bearbeitet diese und speichert '+#13+#10+
' sie dann in der Zieldatei. Lange Dateinamen werden unterstuetzt, wenn diese'+#13+#10+
' in Anfuehrungszeichen stehen.'+#13+#10+
' /B alle durch Quelle deffinierten Bytes werden entfernt.'+#13+#10+
' Wird Ziel angegeben, so wird das Quell-Byte durch das Ziel-Byte '+#13+#10+
' ersetzt.'+#13+#10+
' Quelle und Ziel muessen Dezimalzahlen zwischen 0 und 255 sein.'+#13+#10+
' /UCase alle Kleinbuchstaben werden in Groszbuchstaben geaendert.'+#13+#10+
' /LCase alle Groszbuchstaben werden in Kleinbuchstaben geaendert.'+#13+#10+
' /NoInfo Ausgaben auf den Bildschirm werden unterdrueckt.'+#13+#10+
''+#13+#10+
'Beispiel:'+#13+#10+
' filter q.dat z.txt /B9:32 /B0 /LCase /NoInfo'+#13+#10+
' (ersetze alle Tabulatoren durch Leerzeichen, entferne alle Null-Bytes,'+#13+#10+
' wandle alle Grosz- in Kleinbuchstaben, keine Bildschirmausgaben)'+#13+#10);
end;
if error=EKeinFehler then begin // zu wenige Parameter
if paramcount<2 then error:=EParameteranzahl;
end;
if (error=EKeinFehler)and(paramcount>2)then begin //Auswertung d. Parameter
for n:=3 to paramcount do begin
m:=0;
temp:=lowercase(paramstr(n));
if ((pos('/b',temp)=1)and(length(temp)>2)) then begin
m:=1; // erst mal kein Fehler
temp2:=copy(temp,3,length(temp)-2);
o:=pos(':',temp2);
if o>0 then begin //ev. Zielbyte abtrennen
temp3:=copy(temp2,o+1,length(temp2)-o);
delete(temp2,o,length(temp2)-o+1);
end;
val(temp2,b1,code);
if (code<>0)or(b1<0)or(b1>255) then m:=0 //Fehler im Quellbyte
else begin
ZuFiltern[b1]:=true;
if o>0 then begin
val(temp3,b2,code);
if (code<>0)or(b2<0)or(b2>255) then m:=0 //Fehler im Zielbyte
else begin
ZuErsetzen[b1]:=true;
Ersatzcode[b1]:=b2;
end;
end;
end;
end;
if (pos('/ucase',temp)=1) then begin
m:=1;optupcase:=true;
end;
if (pos('/lcase',temp)=1) then begin
m:=1;optlowcase:=true;
end;
if (pos('/noinfo',temp)=1) then begin
m:=1;OptNoInfo:=true;
end;
if m=0 then error:=ESyntaxfehler;
end;
end;
if error=EKeinFehler then begin //Hauptteil
{$I-}temp:=expandfilename(paramstr(1)); AssignFile(Quelle, temp);
FileMode := 0; Reset(Quelle, 1); {$I+}
if ioresult<>0 then error:=ELesefehler;
if error=EKeinFehler then begin
{$I-}temp:=expandfilename(paramstr(2)); AssignFile(Ziel, temp);
Rewrite(Ziel, 1);{$I+}
if ioresult<>0 then error:=ESchreibfehler;
end;
repeat
{$I-}BlockRead(Quelle, Buf, SizeOf(Buf), NumRead){$I+};
if (ioresult<>0) then error:=ELesefehler else begin;
CopyEnd:=(numread=0);
for n:=1 to Numread do begin
if (optupcase and(buf[n]>32))then buf[n]:=ord(upcase(chr(buf[n])));//alle Zeichen in Großbuchstaben
if (optlowcase and(buf[n]>32))then begin//alle Zeichen in Kleinbuchstaben
temp:=chr(buf[n]);temp:=lowercase(temp);buf[n]:=ord(temp[1]);
end;
if ZuFiltern[buf[n]] then begin
if Zuersetzen[buf[n]] then buf[n]:=Ersatzcode[buf[n]] //Zeichen ersetzen
else begin //Zeichen löschen
//hier ev. schnelleres schieben einbauen!!
m:=n; while m<=numread do begin
buf[m]:=buf[m+1];
inc(m);
end;
dec(numread);
end;
end;
end;
counter:=counter+numread;
{$I-}BlockWrite(Ziel, Buf, NumRead, NumWritten){$I+};
if (ioresult<>0) then error:=ESchreibfehler;
end;
until CopyEnd or (NumWritten <> NumRead)or(error<>EKeinFehler) ;
{$I-}CloseFile(Quelle){$I+};
if (ioresult<>0)and(error=EKeinFehler) then error:=ELesefehler;
{$I-}CloseFile(Ziel){$I+};
if (ioresult<>0)and(error=EKeinFehler) then error:=ESchreibfehler;
end;
If (not optnoinfo)and(error<>ehilfe) then begin //Auswertung
writeln(inttostr(counter)+' Bytes geschrieben');
case error of
EKeinFehler:
writeln(paramstr(1)+' wurde fehlerfrei bearbeitet');
ESyntaxfehler,EParameteranzahl:
writeln('Syntaxfehler in der Kommandozeile !!');
ELesefehler:
writeln('Beim Lesen von '+paramstr(1)+' ist ein Fehler aufgetreten !!');
ESchreibfehler:
writeln('Beim Schreiben von '+paramstr(2)+' ist ein Fehler aufgetreten !!');
end;
end;
case error of //Beende mit Errorlevel
ESyntaxfehler: n:=1;
EParameteranzahl:n:=2;
ELesefehler: n:=3;
ESchreibfehler: n:=4;
else n:=0;
end; Halt(n);
end.
|