AGB  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Base64/ Mime für Dateien

Ein Thema von Capstone · begonnen am 13. Sep 2017 · letzter Beitrag vom 17. Sep 2017
Antwort Antwort
Seite 1 von 2  1 2   
Foren-Tage 2017
DIE Konferenz für Delphi-Entwickler mit vielen Vorträgen und ganztägigen Workshops, veranstaltet u.A. von der Delphi-PRAXiS und Embarcadero.
21.-23. September 2017 in Hamburg · Mehr Infos unter forentage.de.
Benutzerbild von Capstone
Capstone

Registriert seit: 15. Jul 2013
Ort: NRW
23 Beiträge
 
Delphi 3 Professional
 
#1

Base64/ Mime für Dateien

  Alt 13. Sep 2017, 11:02
Delphi-Version: 5
So, 2 Dinge brauche ich:
Datei -> base64-String
Datei -> base64-Datei
und zurück.

Wie kann man Dateien am sinnvollsten/schnellsten/besten [Stream/sonstwie] mime codieren:

Ich möchte eine große (ca.80 MB) Datei gerne in base64 sichern/umwandeln. Unüblich ich weiß. Doch das dauerte mit diversen anderen units, die ich über die Jahre mal gefunden habe sonst teilweise für 1 MB StringDaten schon extrem lange.

Erst hatte ich mit der DEC 5.2 Funktion herumgespielt, weil ich gesehn hatte, daß Hagen die Funktion dort auch eingebaut hat. Allerdings, wie mir scheint eher nur für Strings (z.B. den Salt; evtl. auch für den Cryptotext). Oder?

Ich hab dann nochmal gesucht und die Unit von Sakura (wieder)gefunden.
Base64 (MIME) En-/Decoding
Diese oder eine ähliche hab ich vor Jahren schon mal abgespeichert und in einem älteren Projekt eingebunden, fand aber später mal in meinen Projekten, daß die in DEC eingebaute Routine[mime?] für einige tausend/Mio Bytes irgendwie schneller war.

So, nun wollte ich dennoch diese auch verwenden, weil die mit Streams zurechtzukommen scheint, hab aber generelle Probleme damit/ u.mit Streams. (bin auch noch "neu" mit Delphi/pascal)

Streams - dazu hab ich mir mittlerweile was durchgelesen - aber ich kann doch eigentlich nicht in BufferTeilen in eine Base64 Procedur reinschieben - das gibt doch sicher total andere Eegebnisse, als von einem kontinuierlichen Strom? Dann hätte ich ja unterbrochene, einzeln b64 codierte Stringabschnitte.

Wie mach ich das am besten?

"Datei als base64-String" wäre evtl. auch noch gut, für kleinere Dateien.
müßte doch auch gehen?


Delphi-Quellcode:
var
OUTStrom, strm : TFileStream;
FN: String;
  Buffer:array[0..7] of byte;
  Buffer2:array[0..7] of byte;
begin
     begin
FN := 'C:\neu.txt'; // 5 MB groß
    strm:=TFileStream.Create(FN,fmOpenRead);

if not FileExists(FN + 'UUX') then
     FileCreate(FN+ 'UUX');
OUTStrom:=TFileStream.Create(FN + '_ENC' ,fmOpenWrite or fmShareDenyNone);
    strm.Seek(0,soFromBeginning);
   OUTStrom.Seek(0,soFromBeginning);

    Base64Encode(Strm, 8, OUTStrom);
   strm.Free;
   OUTStrom.Free;
  end;

Hab das einfach mal so versucht, mit dem, was ich mir über Streams so zusammengoogeln konnte.
Die Buffergröße ist ... einfach mal geschätzt gewählt. Ob die sinnvoll ist, weiß ich nicht.

Jedenfalls bricht das Programm bei Durchführung einfach ab und bleibt im CPU Diassembler stehen:
datatype missalignment at 0x77b4d7e8.

Naja, vielleicht wißt Ihr ja, wie man das insgesamt besser lösen könnte.
Ich kenn mich mit Streams nicht so aus. Anfangs hatte ich darum eine Stringlist.loadfromFile('neu.txt') als Speicher verwenden wollen, aber das ging auch nicht, da dann nur die erste, kurze Zeile verwendet wurde.

Eine Suche hier im Forum und entwEcke nach Datei und Mime oder base64 brachte vieles, aber auch viele Threads, in denen die das mit Indy lösten.
Zudem hab ich aber Delphi 5. (64 Bit brauch ich nicht)



Vielleicht hat jemand eine Idee und einen Moment Zeit zu antworten.
(Der umgekehrten Weg (b64Decode) ist hoffentlich genauso einfach.?)

Danke.
MySQL-ERROR(): 1146
- - - Entschuldigung,
Diese Signatur ist in Deinem Land nicht vollständig sichtbar. :/
PGP Key ID: 0xB54AACD6
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.397 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: Base64/ Mime für Dateien

  Alt 13. Sep 2017, 11:23
Warum nutzt Du nicht die TIdEncoderMIME Klasse der Indy-Unit IdCoderMIME? Damit geht es recht einfach und schnell.
Delphi-Quellcode:
  FileToEncode := TFileStream.Create(aFileNameSource, fmOpenRead);
  FileAsBase64 := TFileStream.Create(aFileNameDest, fmCreate);
  try
    idCodec64.Encode(FileToEncode, FileAsBase64);
  finally
    FileAsBase64.Destroy;
    FileToEncode.Destroy;
  end;
Bei mir dauern 80 MB etwas mehr als 4 Sekunden.

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von Capstone
Capstone

Registriert seit: 15. Jul 2013
Ort: NRW
23 Beiträge
 
Delphi 3 Professional
 
#3

AW: Base64/ Mime für Dateien

  Alt 13. Sep 2017, 12:15
Warum nutzt Du nicht die TIdEncoderMIME Klasse der Indy-Unit IdCoderMIME? Damit geht es recht einfach und schnell.[...]
weil ...

äh ja, weil

Du (EDIT: damals) selbst geschrieben hast:
Zitat von Sakura:
Erster Grund contra der Indy Lösung: es ist eine Komponente (VCL).
Zweiter Grund contra der Indy Lösung: die ist seht langsam
siehe Base64 (MIME) En-/Decoding

Das hab ich ernst genommen.

und langsame units kannte ich schon, die hab ich reichlich im Netz gefunden. (wohl eher für kurze Strings geeignet.)

Und da dachte ich mir ... wenn schon ... dann eine Assembler Lösung. Schneller kann's nicht gehen.
64Bit muß nicht sein.

Aber Danke Dir, Sakura,
aber da muß ich erstmal schauen, ob ich die Indy für D5 überhaupt noch bekomme.

http://ww2.indyproject.org/Archive/index.DE.aspx

http://ww2.indyproject.org/Archive/index.html
Code:
404 - File or directory not found.
The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.
Oar .. wie ich solche Seiten Liebe ...

hier hab ich zwar auch noch nen passenden Thread gefunden, aber da sind leider auch nur alte Links.
Indy für Delphi 5 Standard

Ich denke, da wird es auch nur noch Indy 9 für so alte Delphi5 geben ... meine ich, hätt ich mal gelesen.

aber wo ... als ZIP-Download?

wo bekommt Ihr das Zeug nur immer her?
MySQL-ERROR(): 1146
- - - Entschuldigung,
Diese Signatur ist in Deinem Land nicht vollständig sichtbar. :/
PGP Key ID: 0xB54AACD6

Geändert von Capstone (13. Sep 2017 um 12:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: München
11.397 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Base64/ Mime für Dateien

  Alt 13. Sep 2017, 12:28
[QUOTE=Capstone;1381024]Du (EDIT: damals) selbst geschrieben hast:
Zitat von Sakura:
Erster Grund contra der Indy Lösung: es ist eine Komponente (VCL).
...
...
...
Ich denke, da wird es auch nur noch Indy 9 für so alte Delphi5 geben ... meine ich, hätt ich mal gelesen.
Gut, D5 hatte ich jetzt nicht mitbekommen. Auch die Indy-Komponenten wurden mit der Zeit verbessert. Aber ob es etwas aktuelleres für D5 überhaupt gibt... Keine Ahnung

Viel Erfolg

......
Daniel W.
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
409 Beiträge
 
Delphi 6 Professional
 
#5

AW: Base64/ Mime für Dateien

  Alt 13. Sep 2017, 12:40
Hmm..


http://indy.fulgan.com/ZIP/


Unter D6 laufen diese problemlos...
Einfach mal testen..
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
108 Beiträge
 
Delphi 2009 Professional
 
#6

AW: Base64/ Mime für Dateien

  Alt 13. Sep 2017, 14:52
Ist an sich schnell geschrieben:
Delphi-Quellcode:
procedure Base64EncodeStream(Input, Output: TStream);
const
  Base64: array[0..64] of Byte = (
  65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
  97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,
  48,49,50,51,52,53,54,55,56,57,43,47,$3D);
var
  count: Byte;
  temp: Cardinal;
  i, j: Integer;
begin
  Count := 0;
  Temp := 0;
  for i := 0 to (Input.Size + 2) div 3 - 1 do
  begin
    Count := Input.Read(temp, 3);
    temp := temp and $ff00 + temp shl 16 + temp shr 16; // Endianness drehen
    for j := 0 to Count do
    begin
      temp := temp shl 6;
      Output.WriteBuffer(Base64[(temp shr 18) and $3f], 1);
    end;
  end;
  for j := Count to 2 do
  Output.WriteBuffer(Base64[64], 1);
end;
Ich würde übrigens TMemoryStreams nehmen. Viele kleine Zugriffe auf TFileStream sind abartig langsam.
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
Benutzerbild von Capstone
Capstone

Registriert seit: 15. Jul 2013
Ort: NRW
23 Beiträge
 
Delphi 3 Professional
 
#7

AW: Base64/ Mime für Dateien

  Alt 15. Sep 2017, 21:01
ich grüße Euch,
und ich Danke Euch für Eure Vorschläge.

mhh, ich schäme mich ja fast, nochmal fragen zu müssen, weil ich immer noch nicht klarkomme.
Ich probier nun schon den ganzen Abend mit verschiedenen Verzeichnissen, Orten , und Tricks, die INDYs installiert zu bekommen, bzw, wenigstens die Units nutzen zu können.

Also:

Indy 9 + 10 hab ich runtergeladen, aber erstmal nur die 9er-ZIP entpackt und die Full5.bat ausgeührt (wegen vermutl. besserer Kompatibilität)
Da wurden anscheinend alle klaglos compiliert. (alle dcu's wurden in C:\INDY\D5 erstellt)
Dann hab ich, wie in der ManualInstall.txt beschrieben
»dclIndy50.bpl« als Komponente bzw. dann auch als Package zu installieren, welche demnach in C:\INDY\d5 sein sollte, aber sich nur in C:\INDY\Source\ befindet.


Zitat:
»To install Indy manually, please do the following:

1. Run the appropriate batch file for your Borland Product.
Delphi 5.0 - c:\Indy\Source\Fulld5.bat
2. In your Integrated Development Evnornment, install the DclIndy*.bpl which is located in the appropriate directory. Those are:
Delphi 5.0 - c:\Indy\d5
3. Add the appropriate directory from the ones listed above to your library path. To do this, click Tools|Environment Options...|Library. Just add the directory in Library path to end of the path preceded by a ";" such as:
;c:\Indy\d5 «
http://www.delphipraxis.net/attachme...1&d=1505503858

Dennoch erhalte ich folgende Fehlermeldung:
"<IDname> ist kein gültiger Bezeichner.

Zitat:
Bezeichner ist lexikalisch ungültig. Achten Sie darauf, daß das erste Zeichen ein Buchstabe oder ein Unterstrich (_) ist. Die folgenden Zeichen können Buchstaben, Ziffern oder Unterstrich-Zeichen sein. Es dürfen sich keine Leerzeichen innerhalb des Strings befinden."
(Quelle: Delphi hlp)

http://www.delphipraxis.net/attachme...1&d=1505503914

Ich hab zwar dann unter Projektoptionen die Pfade zu den Units in das Feld für die Suchpfade eingetragen und zumindest nach implementation die beiden Units eingetragen (uses IdMessageCoder, IdMessageCoderMIME
Da meckert er wenigstens auch nichts dran.
Aber außer, daß ich die Klasse TIdMessageCoderMIME (statt des idCodec64.Encode()) eintippen kann, läßt sich außer .create nicht viel damit machen. Encode ist nicht zu finden.

idCodec64 wird gar nicht angeboten, wenn ich die Kontextergänzung CTRL+Shift + Leer nehme.
Also hatte ich versucht die Procedur TIdMessageCoderMIME zu verwenden. Auch nix.

Da ist also kein Weiterkommen, oder?
Mhh, jetzt ist das ja für Euch mit 90% Delphi 10 auch schwer, da irgendwas zu diagnostizieren, was da einer mit seinem alten Delphi5 macht. Zudem sitz ich ja noch so weit weg. (oder gibt es im Raum Essen irgendwo Delphi Leute?)

------

Dann habe ich allerdings auch heute Nachmittag schon probiert, ob ich die Lösung von Redeemer umsetzen könnte.
Doch war ich daran auch gescheitert.

Delphi-Quellcode:
procedure TForm1.Button5Click(Sender: TObject);
var fin, fon : TMemoryStream;
FN : String;
err: Boolean;
begin
   FN := 'C:\Users\Documents\DELPHI\b64\neu.txt';
  fin :=TMemoryStream.Create(FN,fmOpenRead); // hier wären die Argumente zu viel/unpassend

  fon :=TMemoryStream.Create(FN + '2',fmOpenWrite);

err := Base64EncodeStream (fin, Fon);
if Err then Caption := 'FEHLER';

fin.free;
son.free;

end;
Dann hab ich das hier
Delphi-Quellcode:
procedure TForm1.Button5Click(Sender: TObject);
var fin, fon : TMemoryStream;
fiS, foS : TFileStream;
FN : String;
err: Boolean;
begin
   FN := 'C:\Users\Documents\DELPHI\b64\neu.txt';

   Fis := TFileStream.Create(FN,fmOpenRead);
   FOS := TFileStream.Create(FN + 2,fmOpenRead);

// fin := Fis; //TMemoryStream.Create(FN,fmOpenRead); // FAIL
// fin.assign(Fis); // FAIL

  fon := TMemoryStream.Create(FN + '2',fmOpenWrite); // FAIL


err := Base64EncodeStream (fiS, FoS);

if Err then Caption := 'FEHLER';

fin.free;
son.free;

end;
versucht.
Aber das geht ja auch nicht.

Wie gesagt mit Streams kenn ich mich nicht so aus.
Ich hab zwar ein kurzes Buch, das behandelt Streams aber nur so am Rande. Eher Klick, Klick, Edit = fertig ist das Programm.
Wüßte auch nicht, wo man sowas - und dann noch auf dieses Problem spezialisiert, gut lernen/lesen könnte.

Also was ich bräuchte wären Datei->b64-Datei und Datei->b64-String Funktionen.

Was mach ich denn falsch?
Miniaturansicht angehängter Grafiken
2017-09-15_212140-.png   2017-09-15_211426.png  
MySQL-ERROR(): 1146
- - - Entschuldigung,
Diese Signatur ist in Deinem Land nicht vollständig sichtbar. :/
PGP Key ID: 0xB54AACD6

Geändert von Capstone (15. Sep 2017 um 21:07 Uhr)
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
108 Beiträge
 
Delphi 2009 Professional
 
#8

AW: Base64/ Mime für Dateien

  Alt 15. Sep 2017, 21:09
Meine Methode (oder besser gesagt MemoryStreams) benutzt man so:
Delphi-Quellcode:
var
  Input, Output: TMemoryStream;
begin
  Input := TMemoryStream.Create;
  Output := TMemoryStream.Create;
  try
    Input.LoadFromFile('meinedatei.bin');
    Base64EncodeStream(Input, Output);
    Output.SaveToFile('meinedatei.txt');
  finally
    Input.Free;
    Output.Free;
  end;
end;
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer (15. Sep 2017 um 21:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Capstone
Capstone

Registriert seit: 15. Jul 2013
Ort: NRW
23 Beiträge
 
Delphi 3 Professional
 
#9

AW: Base64/ Mime für Dateien

  Alt 15. Sep 2017, 21:33
Danke, funktioniert jetzt auch bei mir so - in der Tat.
aber wo kann ich sowas nachlesen?

Genau so ein Wissen fehlt mir ja.

EDIT:
aber
also mit folgendem Code braucht er für ne 17 MB Datei (ca. 20 Sekunden?).
(19969 Tics)

Ne 5000 Bytes-Datei geht schneller: 2044 Tics.

10000 Bytes Datei: 6973 Tics.

(hab hier nen 4 Jahre alten 2x 2.54 DualCore Laptop, 8 GB RAM, 1 TB HDD) Aber das kommt mir irgendwie langsam vor, oder?.
Delphi-Quellcode:
procedure TForm1.Button6Click(Sender: TObject);
var
  Input, Output: TMemoryStream;
  FN: String ;
  gt, gt2: Longword;
diff : integer;
begin
  Input := TMemoryStream.Create;
  Output := TMemoryStream.Create;
  try
  FN := 'C:\Users\Documents\DELPHI\fC\neu.txt';
      gt := gettickcount;
    Input.LoadFromFile(FN );
    Base64EncodeStream(Input, Output);
      Output.SaveToFile(FN + 'UUX');
          gt2 := gettickcount;
          diff:= gt2 - gt;
// diff := diff * 1000;
  memo1.Text:= inttostr(diff);

  finally
    Input.Free;
    Output.Free;
  end;
end;
Schrieb Sakura nicht was von wenigen Sekunden? (4S für 80 MB?)
MySQL-ERROR(): 1146
- - - Entschuldigung,
Diese Signatur ist in Deinem Land nicht vollständig sichtbar. :/
PGP Key ID: 0xB54AACD6

Geändert von Capstone (15. Sep 2017 um 22:19 Uhr)
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
108 Beiträge
 
Delphi 2009 Professional
 
#10

AW: Base64/ Mime für Dateien

  Alt 15. Sep 2017, 22:09
Habe das bei mir mit 90 MB getestet, dauerte etwa zwei Sekunden. Aber das war 'ne SSD. Mach mal die Ticks nur um meine Methode. Die sollte deutlich unter einer Sekunde brauchen, gerade für nur 17 MB.

Man sollte beim Programmieren schon lesen, was da steht. Wenn man Input := TMemoryStream.Create( eingibt, erscheint automatisch die Programmierhilfe von Delphi und sagt „<Keine Parameter erwartet>“. Also ruft man die Methode ohne Parameter auf (Klammer wieder weg oder – wer’s mag – Klammer sofort schließen). Da hätten schon längst deine Alarmglocken schrillen sollen. Wenn die Methode keine Parameter erwartet, sind zwei Parameter natürlich zu viel.

Ich habe noch nie ein Buch zu Delphi gelesen. Es begann mit der Anleitung zur Programmierung eines Euro-DM-Umrechners in PC-World, wo Delphi 6 PE beilag. Rest über die Dokumentation. (Das übt zwar die Aneignung von Wissen aus der Dokumentation, aber die Code-Qualität und Umsetzung früherer Projekte ist allerdings dementsprechend schlecht, da man z.B. nicht immer weiß, welche weiteren (besseren) Möglichkeiten es noch gibt, um dasselbe Problem zu lösen.)
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer (15. Sep 2017 um 22:11 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2017 by Daniel R. Wolf