Filter.exe

  Hauptseite/ Programmieren



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







 filter /? b.z.w filter /help liefert diese Hilfe:
DOS-Box







 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.


  Hauptseite/ Programmieren