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. Download: filter.zip (ca.29KByte) Hilfe Delphi-Quellcode |
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. |