Solved

streams

Posted on 2002-06-22
16
399 Views
Last Modified: 2010-04-04
i need to be able to add together 'x' streams into one stream and then take all the seporate the one stream back into 'x' streams.
plz help asap!
0
Comment
Question by:mgazza
  • 9
  • 4
  • 3
16 Comments
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
a sample from my paq,

splitting and concanating back any file by using any fragment size

unit splitfiles_u;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
  Button1: TButton;
  OpenDialog1: TOpenDialog;
  Edit1: TEdit;
  SaveDialog1: TSaveDialog;
  Button2: TButton;
  Label1: TLabel;
  procedure Button1Click(Sender: TObject);
  procedure Button2Click(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

//Splitting Files
procedure TForm1.Button1Click(Sender: TObject);
var
i, WantedFragSize, RealToWrite : Integer;
InStream, OutStream : TFileStream;
S : String;
begin
if Opendialog1.Execute then
begin
  SaveDialog1.Title := 'Select Dir and input FilePrefix without Suffix';
  If SaveDialog1.Execute then
  begin
    WantedFragSize := StrtoInt(Edit1.Text);  //Wanted SplitSize
    i := 0;
    InStream  := TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
    try
      while (InStream.Position < InStream.Size) do
      Begin
        s := IntToStr(I);                   //Building numeric suffix
        while Length(s) < 3 do s := '0'+s;
        s := '.'+s;
        If InStream.Size - InStream.Position < WantedFragSize then
          RealToWrite := InStream.Size - InStream.Position
        else
          RealToWrite := WantedFragSize;
        OutStream  := TFileStream.Create(SaveDialog1.FileName+s,fmCreate);
        try
          OutStream.CopyFrom(InStream,RealToWrite);
          Inc(i);
        finally
          OutStream.Free;
        end;
      end;
    Finally
      InStream.Free;
    end;
  end;
end;
end;

//concanating files
procedure TForm1.Button2Click(Sender: TObject);
var
i : Integer;
InStream, OutStream : TFileStream;
SourcePath, FragName, S : String;
begin
Opendialog1.Title := 'Select any Fragmented File';
if Opendialog1.Execute then
begin
  SourcePath := ExtractFilePath(Opendialog1.FileName);
  FragName := ExtractFileName(Opendialog1.FileName);
  SaveDialog1.Title := 'Select Dir and input the FileName with Suffix';
  If SaveDialog1.Execute then
  begin
    i := 0;
    s := IntToStr(I);
    while Length(s) < 3 do s := '0'+s;
    s := '.'+s;
    FragName := ChangeFileExt(FragName, s);
    If FileExists(SourcePath+FragName) then
    begin
      OutStream := TFileStream.Create(Savedialog1.FileName,fmCreate);
      try
        While FileExists(SourcePath+FragName) do
        Begin
          InStream  := TFileStream.Create(SourcePath+FragName,fmOpenRead);
          try
            OutStream.CopyFrom(InStream,0);
            Inc(i);
            s := IntToStr(I);
            while Length(s) < 3 do s := '0'+s;
            s := '.'+s;
            FragName := ChangeFileExt(FragName, s);
          finally
            InStream.Free;
          end;
        end;
      finally
        OutStream.Free;
      end;
    end;
  end;
end;
end;

end.

meikl ;-)
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
nice fancy bit of coding iv been trying to do something like tha 4 ages can't try it now int 1:00 am i will try it in the moring well when its light thanks ne way
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
sos i dont know how to use it
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
splitfiles
-just type a number in the edit = fragmentsize in bytes
-press button1->select a file->file is splitted now->splitted files have as name filename.numbercount

concanating files
-select one splitted file
-give the desination filename->splitted files are concanted to the given filename

just tell me, where you have a problem,
if needed i can send you the compiled project
(leave your mail-adress here, in this case)

meikl ;-)
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
this adds togeterth all the files into one file what i need now is something that searches for [newfile] and writes it out to a nother stream this works fine for the first file but when writing the second file it writes the first file in it heres the bit of code for adding the files together(this part works fine);

procedure TForm1.Button1Click(Sender: TObject);
var
ins,outs:tmemorystream;
i:integer;
temp:tstringlist;
begin
temp:=tstringlist.Create;
ins:=tmemorystream.Create;
outs:=tmemorystream.Create;
temp.Text:='[newfile]';
for i:=0 to strtoint(edit1.text)-1 do
begin
opendialog1.Execute;
ins.LoadFromFile(opendialog1.FileName);
ins.SaveToStream(outs);
temp.SaveToStream(outs);
end;
savedialog1.Execute;
outs.SaveToFile(savedialog1.FileName);
end;

0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
this adds togeterth all the files into one file what i need now is something that searches for [newfile] and writes it out to a nother stream this works fine for the first file but when writing the second file it writes the first file in it heres the bit of code for adding the files together(this part works fine);

procedure TForm1.Button1Click(Sender: TObject);
var
ins,outs:tmemorystream;
i:integer;
temp:tstringlist;
begin
temp:=tstringlist.Create;
ins:=tmemorystream.Create;
outs:=tmemorystream.Create;
temp.Text:='[newfile]';
for i:=0 to strtoint(edit1.text)-1 do
begin
opendialog1.Execute;
ins.LoadFromFile(opendialog1.FileName);
ins.SaveToStream(outs);
temp.SaveToStream(outs);
end;
savedialog1.Execute;
outs.SaveToFile(savedialog1.FileName);
end;

0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
this adds togeterth all the files into one file what i need now is something that searches for [newfile] and writes it out to a nother stream this works fine for the first file but when writing the second file it writes the first file in it heres the bit of code for adding the files together(this part works fine);

procedure TForm1.Button1Click(Sender: TObject);
var
ins,outs:tmemorystream;
i:integer;
temp:tstringlist;
begin
temp:=tstringlist.Create;
ins:=tmemorystream.Create;
outs:=tmemorystream.Create;
temp.Text:='[newfile]';
for i:=0 to strtoint(edit1.text)-1 do
begin
opendialog1.Execute;
ins.LoadFromFile(opendialog1.FileName);
ins.SaveToStream(outs);
temp.SaveToStream(outs);
end;
savedialog1.Execute;
outs.SaveToFile(savedialog1.FileName);
end;

0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
well, could you tell me, what you want to do?
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 2

Expert Comment

by:mikepj
Comment Utility
I needed to do this recently.  Effectively this is what I did; more detailed example available.

You'd need to save it with the size info something like this:

var
  iBytes:cardinal;
begin
  iPart1Bytes:=strm1.Size;
  strmOut.WriteBuffer(iBytes,sizeof(iBytes));

  iPart2Bytes:=strm2.Size;
  strmOut.WriteBuffer(iBytes,sizeof(iBytes));

  strmOut.CopyFrom(strm1,strm1.Size);
  strmOut.CopyFrom(strm2,strm2.Size);
  ....
end;

To get your data out, you'd need to do something like:

var
  iBytes:cardinal;
begin
  strmIn.ReadBuffer(iBytes,sizeof(iBytes));
  strm1.CopyFrom(strmIn,iBytes);

  strmIn.ReadBuffer(iBytes,sizeof(iBytes));
  strm2.CopyFrom(strmIn,iBytes);
  ...
end;
0
 
LVL 2

Expert Comment

by:mikepj
Comment Utility
Oops; I mixed up the answer.  Here it is again

var
 iBytes:cardinal;
begin
 ...
 iBytes:=strm1.Size;
 strmOut.WriteBuffer(iBytes,sizeof(iBytes));
 strmOut.CopyFrom(strm1,strm1.Size);

 iBytes:=strm2.Size;
 strmOut.WriteBuffer(iBytes,sizeof(iBytes));
 strmOut.CopyFrom(strm2,strm2.Size);
 ...
end;

To get your data out, you'd need to do something like:

var
 iBytes:cardinal;
begin
 ...
 strmIn.ReadBuffer(iBytes,sizeof(iBytes));
 strm1.CopyFrom(strmIn,iBytes);

 strmIn.ReadBuffer(iBytes,sizeof(iBytes));
 strm2.CopyFrom(strmIn,iBytes);
 ...
end;
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
sorry! iv been on my hols !sorry 4 no replying!
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
here is i bit iv been working on but it dont work

procedure TForm1.Button1Click(Sender: TObject);
var
s1,s2,s3:tstringlist;
strem1:tmemorystream;
i,ii,iii,del:integer;
begin
strem1:=tmemorystream.Create;
s1:=tstringlist.Create;
s2:=tstringlist.Create;
s3:=tstringlist.Create;

opendialog1.Execute;
strem1.LoadFromFile(opendialog1.FileName);
s1.LoadFromStream(strem1);
/////first
for i:=0 to s1.Count-1 do
begin
if s1.Strings[i]='[newfile]'  then
s2.AddObject(inttostr(random(400000)),tmemorystream.Create);
end;
///////next
for iii:=0 to s2.Count-1 do
begin
ii:=0;
while s1.Strings[ii]<>'[newfile]' do
begin
s3.Add(s1.Strings[ii]);
ii:=ii+1;
end;
//
for del:=0 to s3.Count-1 do
begin
s1.delete(del);
end;
//
savedialog1.Execute;
s3.SaveToStream(tmemorystream(s2.Objects[iii]));
tmemorystream(s2.Objects[iii]).SaveTofile(savedialog1.FileName);
s3.Clear;
tmemorystream(s2.Objects[iii]).free;

end;


end;

does your bit of code add files together and take them apart?
if so mail me the sorce code! rcmgazza2@hotmail.com!
thank you!!!
0
 
LVL 2

Expert Comment

by:mikepj
Comment Utility
Yes; I put a string list and a binary file in the same file.  Essentially what I did is:

1) Write a 4 byte file content marker
2) Write the length of the string list as a string
3) Write the string list as a string
4) Write the length of the binary file
5) Write the binary file

Parts 2 and 3 are handled by the routine below
Part 4 I actually skipped because I didn't need it

To read it:

1) Read and check the 4 byte content marker
2) Read the length of the string list as a string
3) Read n bytes
4) Read the string list string
5) Read the length of the binary section
6) Read the binary section

Parts 2-4 are handled by the routine below.
Part 5 I actually skipped because I didn't need it

The TStringList.SaveToStream and LoadToStream methods aren't as good as you might expect...they pay no attention to the length of the string written.  I expanded my TStringList descendant as follows so that the size will always be written and considered upon read.

  TMyStringList = Class(TStringList)
    Published
      procedure SmartSaveToStream(strm:TStream);
      procedure SmartLoadFromStream(strm:TStream);
    End;

procedure TMyStringList.SmartSaveToStream(strm:TStream);
var
  iBytes:cardinal;
  s:string;
begin
  s:=Text;
  iBytes:=Length(s);
  strm.WriteBuffer(iBytes,sizeof(iBytes));
  strm.WriteBuffer(Pointer(S)^, Length(S));
end;

procedure TMyStringList.SmartLoadFromStream(strm:TStream);
var
  iBytes:cardinal;
  s:string;
begin
  strm.ReadBuffer(iBytes,sizeof(iBytes));
  SetLength(s,iBytes);
  strm.ReadBuffer(Pointer(S)^, Length(S));
  Text:=s;
end;

This code will allow you to blindly write as many stringlists to the stream and blindly read them back without needing to worry about the length.

If you need more, I could provide more info.

MP
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
email me the full file adder  .pas .dfm ziped up thanks!;-)
0
 
LVL 1

Author Comment

by:mgazza
Comment Utility
var
sizelog:tstringlist;
mainfile:tmemorystream;
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
sizelog:=tstringlist.Create;
mainfile:=tmemorystream.Create;
end;
 //winzip drag drop
procedure TForm1.Button1Click(Sender: TObject);
var
nowfile:tmemorystream;
begin
nowfile:=tmemorystream.Create;
if opendialog1.Execute then
begin
nowfile.LoadFromFile(opendialog1.FileName);
sizelog.Add(inttostr(nowfile.size));
nowfile.SaveToStream(mainfile);
end;
end;
 //winzip close write
procedure TForm1.Button2Click(Sender: TObject);
var
thestrings:tmemorystream;
begin
thestrings:=tmemorystream.Create;
sizelog.SaveToStream(thestrings);
//double the strings size to the main filesize
thestrings.SetSize(mainfile.Size);
thestrings.SaveToStream(mainfile);

savedialog1.Execute;
mainfile.SaveToFile(savedialog1.FileName);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
files,strings:tmemorystream;
resetsizes:tstringlist;
begin
strings:=tmemorystream.Create;
files:=tmemorystream.Create;
resetsizes:=tstringlist.Create;

if opendialog1.Execute then
begin

/////continued
end;

here is a notherway of adding files and taking them apart!!
this one will work!!!
compile this and i will show you what it needs next!
///@ the continue
"files"  needs to read the first half of the file and
"strings" needs to read the second half of the file;
save "strings" to "resetsizes" and
then "files" needs to be splitup and each part saved into the sizes shown by each string in "resetsizes" !!!!;-)
0
 
LVL 2

Accepted Solution

by:
mikepj earned 75 total points
Comment Utility
You've made the writing of the file as complex as possible and then hope I'll write the code for reading.  I don't see why you did many of the things you did in your last example.

For 60 points I don't write code.  There are MANY ways to accomplish what you want.  I have given you a nice simple solution that works.  

You presume that I would give you my DFM and PAS file showing the use of this but that comprises 1500 lines of code for many things.  Apart from my not wanting to release my code, it would cause more confusion and questions for you than it's worth.

Instead I've snipped out the "guts" of the stream append and split.  Use it only as an example.  Once you understand the example, adapt yours to do something similar.  The ZCompress/ZDecompress compresses the binary stream and adds it to the end of the text stream.  SmartSaveToStream and SmartLoadFromStream take care of the length tracking.

MP

// export

      strSrce:=TFileStream.Create(sTempFile,fmOpenRead+fmShareDenyNone);

      // protect against strSrce memory leak in case strDest fails
      try
        strDest:=TFileStream.Create(sDest,fmCreate);
      except
        strSrce.Free;
        raise;
      end;

      slExportInfo:=TMyStringList.Create;
      try  // finally
        // file ID marker
        strDest.Write(g_scMarker[1],Length(g_scMarker));

        slExportInfo.Values[g_scFileType]:=g_scExportTypeData;
        slExportInfo.Values[g_scExportTitle]:=edtTitle.Text;
        slExportInfo.SmartSaveToStream(strDest);

        // the rest of the stream is entirely zip content
        ZCompressStream(strSrce,strDest);
      finally
        strDest.Free;
        strSrce.Free;
        slExportInfo.Free;
      end;


// import

    strSrce:=TFileStream.Create(sFilename,fmOpenRead+fmShareDenyNone);

    // protect against strSrce memory leak in case strDest fails
    try
      strDest:=TFileStream.Create(sTempFile,fmCreate);
    except
      strSrce.Free;
      raise;
    end;

    slImportInfo:=TMyStringList.Create;
    try  // finally
      SetLength(sMarker,Length(g_scMarker));
      strSrce.Read(sMarker[1],Length(sMarker));

      if sMarker<>g_scMarker then
        Raise EUserProblem.CreateFmt('Import file "%s" is not suitable for '+g_sProgName,[sFilename]);

      slImportInfo.SmartLoadFromStream(strSrce);

      sFileType:=slImportInfo.Values[g_scFileType];

      if sFileType<>g_scExportTypeData then
        Raise EUserProblem.CreateFmt('File type %s is not suitable for '+g_sProgName,[sFileType]);

      // the rest of the stream is entirely zip content
      ZDecompressStream(strSrce,strDest);
    finally
      strSrce.Free;
      strDest.Free;
      slImportInfo.Free;
    end;

-end-
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now