[Delphi] Filestream hergebruiken

Pagina: 1
Acties:

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Ik werk met een TFileStream :
code:
1
2
3
4
5
FileStream:=TFileStream.Create('c:\CDFOON\subscriber.txt',fmOpenRead);

[i]Berg code hier[/i]

FileStream.Free;

Maar daarna moet ik in een andere file gaan zoeken, en dat wil ik ook met een filestream doen. Kan ik, lijkt me, net zo goed die filestream voor gebruiken en binden aan een andere file. Maar als ik 'em opnieuw creeer, en daarna wil gebruiken, krijg ik een Access Violation.

Hoe kan dat ? Ik kan toch (nadat ik .Free heb gedaan) gewoon opnieuw die FileStream creeeren ?

Mother, will they like this song?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:34
Je doet dus:
code:
1
2
3
4
5
6
FileStream:=TFileStream.Create('...',fmOpenRead);
...
FileStream.Free;
FileStream:=TFileStream.Create('...',fmOpenRead);
...
FileStream.Free;

Ik kan niet echt Delphi programmeren, maar dat lijkt me goed. Als je de tweede keer echter:
code:
1
FileStream.Create('...');

doet, kan ik me voorstellen dat het fout gaat, aangezien je van een vrijgegeven object geen methode kan aanroepen.

Misschien kan iemand die wél Delphi kan je verder helpen. ;)

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Laten we dat maar hopen ja :+ Dat had ik namelijk als eerste al geprobeerd.

Mother, will they like this song?


Verwijderd

Tuurlijk kan dat; vind het wel misplaatste zuinigheid: een pointer naar een TFileStream is maar 4 bytes.

Als je hierbij een AV krijgt ligt dat iig niet aan het feit dat je een var hergebruikt.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:41

Tomatoman

Fulltime prutser

Op vrijdag 12 juli 2002 21:14 schreef Soultaker het volgende:
Ik kan niet echt Delphi programmeren, maar dat lijkt me goed. Als je de tweede keer echter:
code:
1
TFileStream.Create('...');

doet, kan ik me voorstellen dat het fout gaat, aangezien je van een vrijgegeven object geen methode kan aanroepen.
Daar is helemaal niets mis mee.

Oplossing: gewoon voor iedere file een aparte TFileStream gebruiken. Je zult geen enkel performanceverschil merken als je een TFileStream probeert te hergebruiken.

Een goede grap mag vrienden kosten.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:34
Op vrijdag 12 juli 2002 21:35 schreef tomatoman het volgende:
Daar is helemaal niets mis mee.
Zeg grapjas, ik mag dan geen Delphi kunnen coden, maar ik liet die T daar met een reden weg! ;) Wil je me dus wel correct quoten alsjeblieft?

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
4 bytes ?? Hoe krijgt ie dat dan voor mekaar, als de filename al meer dan 4 bytes groot is ?


(note : Ik weet niks van pointers :) )

Mother, will they like this song?


Verwijderd

Op vrijdag 12 juli 2002 23:00 schreef TheLunatic het volgende:
4 bytes ?? Hoe krijgt ie dat dan voor mekaar, als de filename al meer dan 4 bytes groot is ?


(note : Ik weet niks van pointers :) )
De pointer is een variabele van 4 bytes welke het adres van een geheugenlocatie bevat waar het filestreamobject is opgeslagen. Het filestreamobject zelf neemt natuurlijk wel meer dan 4 bytes geheugenruimte in beslag.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:41

Tomatoman

Fulltime prutser

Op vrijdag 12 juli 2002 22:08 schreef Soultaker het volgende:

[..]

Zeg grapjas, ik mag dan geen Delphi kunnen coden, maar ik liet die T daar weg, omdat ik hem had vergeten. ;) Wil je me dus wel correct quoten alsjeblieft?
Ja meneer, ik zal het nooit meer doen. ;)

Een goede grap mag vrienden kosten.


  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Okay, thanks for explaining :)


Maarehm, ik weet nu wel dat een FileStream meer of minder er niet toe doet, maar het moet toch gewoon kunnen zoals ik het wil of niet ? Ze hoeven niet gelijktijdig worden gebruikt, dus dan kan ik mooi mijn code netjes houden ... En daarbij, ik wil het gewoon weten :P

Mother, will they like this song?


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 20:41

Tomatoman

Fulltime prutser

[Edit] Laat maar, niet goed gelezen. :o

Een goede grap mag vrienden kosten.


Verwijderd

Het kan zeker, als je zoiets als dit doet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var AFileStream: TFileStream;

begin
  AFileStream := TFileStream.Create('Blaat1.txt');
  .
  { Mishandel AFileStream }
  . 
  AFileStream.Free;
  AFileStream := nil; { optioneel }

  AFileStream := TFileStream.Create('Blaat2.txt');
  .
  { Mishandel AFileStream }
  . 
  AFileStream.Free;
end.

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Nee hoor, the problem remains. Ook al ik FileStream:=Nil gebruik, nog steeds een AccessViolation. En ik doe het precies op de manier die hierboven staat.

Mother, will they like this song?


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Op zaterdag 13 juli 2002 14:12 schreef TheLunatic het volgende:
Nee hoor, the problem remains. Ook al ik FileStream:=Nil gebruik, nog steeds een AccessViolation. En ik doe het precies op de manier die hierboven staat.
Ok, ik ga morgen de boel uitzoeken want wat je beschrijft zou gewoon moeten kunnen.
In the meantime zou ik je toch willen vragen waarom je toch in vredesnaam die TFileStream wilt hergebruiken:
a. de variabele die je declareert, ga je in 1 procedure voor 2 verschillende doeleinden gebruiken. Dat is niet bepaald bevorderlijk voor de inzichtelijkheid van je code. Waarom niet gewoon
code:
1
2
3
4
5
6
procedure MishandelFiles;
var
  CDFoonStream : TFileStream;
  TheOtherFileStream : TFileStream;
begin
end;

Dan is het in je code tenminste duidelijk welke operaties op je FileStream objecten op welke files betrekking hebben.

b. Je bent nu al veel te lang aan het zoeken naar de oorzaak van het probleem, terwijl je de oplossing al sinds (ik meen) post 2 voorhanden had, nl 2 TFileStream variabelen. (NOFI)

Punt b neemt niet weg dat ik ook nieuwsgierig ben geworden naar de vraag waarom je niet 2x de TFileStream kan gebruiken :) Maar nieuwsgierigheid lost je probleem niet op.

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Ik ben het dus op beide punten met je eens :) Ik heb het nu al zo gemaakt als jij beschreef, en ik moet toegeven, duidelijker is het wel ! Maar ik vind gewoon dat het moet kunnen, en daarom wil ik heb gewoon weten :P

Mother, will they like this song?


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

code:
1
2
3
4
5
6
7
8
9
10
11
procedure TForm1.Button1Click(Sender: TObject);
var AFileStream: TFileStream;
begin
  AFileStream := TFileStream.Create('blaat1.txt', fmOpenRead);
  Memo1.Lines.LoadFromStream(AFileStream);
  FreeAndNil(AFileStream);

  AFileStream := TFileStream.Create('blaat2.txt', fmOpenRead);
  Memo2.Lines.LoadFromStream(AFileStream);
  FreeAndNil(AFileStream);
end;

Werkt perfect hoor. Weet je zeker dat je bestanden bestaan en dat je ze met de juiste modes opend? Wat is de melding van de access violation precies? En op welke regel krijg je die?

Zelfs zonder een FreeAndNil werkt het gewoon, je hebt alleen een memory leak dan.

We adore chaos because we like to restore order - M.C. Escher


  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
De exacte error (eigenlijk onnodig overtypewerk lijkt me)

Project ProjectFile.exe raised exception class EAccessViolation with message 'Access violation at address 0044AA08 in module 'ProjectFile.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.

In de ene procedure

FileStream:=TFileStream.Create('c:\CDFOON\subphone.idx',fmOpenRead);
FileStream.Free;

In de andere procedure

FileStream:=TFileStream.Create('c:\CDFOON\subscriber.txt',fmOpenRead);
FileStream.Free;


En hij loopt vast op de regel

FileStream.Seek(FindIndex(PhoneNumber),soFromBeginning);



Echt vaag, ook als ik FreeAndNil(FileStream) of FileStream:=Nil gebruik, krijg ik de error.

Mother, will they like this song?


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Op zondag 14 juli 2002 18:16 schreef TheLunatic het volgende:
[..]
En hij loopt vast op de regel

FileStream.Seek(FindIndex(PhoneNumber),soFromBeginning);

Echt vaag, ook als ik FreeAndNil(FileStream) of FileStream:=Nil gebruik, krijg ik de error.
Hier komt een stukje aap uit de mouw :)
Een setje vragen.
1. Heb je met debugger bevestigd, met een breakpoint op bovenstaande regel, dat FileStream <> nil?
2. Wat is FindIndex? Wat doet dat?
3. Wat is PhoneNumber? Wat voor type, welke waarde, enz?
4. Plz confirm, dat de 2 FileStream objecten in 2 VERSCHILLENDE procedures zitten, zoals je suggereert.

Met andere woorden, ik krijg de indruk dat je ergens een programming error hebt gemaakt, dat je die nu over het hoofd ziet, en dat wij nu te weinig informatie hebben om de oorzaak op te sporen :)
Eigenlijk ben ik benieuwd naar de gehele 2e procedure waarin de Seek crasht, maar goed je probleem is al opgelost, dus als je er geen tijd meer in wilt steken mij best.

  • TheLunatic
  • Registratie: April 2001
  • Laatst online: 09-07 16:41

TheLunatic

Ouwe boxen.

Topicstarter
Terwijl ik je vraag nummer 2 wil gaan beantwoorden, zie ik ineens wat het probleem is !! In de procedure waar ik de filestream wil gaan hergebruiken, wordt een andere procedure aangeroepen waar de filestream ook gebruikt wordt.

Check, eerst de funcite waar het programma in vastliep
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function TForm1.GetCallerInfo(PhoneNumber: String): TSubscriber;
var Line: String;
    Character: Char;
begin
  FSSubscriber:=TFileStream.Create('c:\CDFOON\subscriber.txt',fmOpenRead);
  FSSubscriber.Seek(FindIndex(PhoneNumber),soFromBeginning);
  while not (Character=#13) do
    begin
    FSSubscriber.Read(Character, 1);
    Line:=Line+Character;
    end;
  with Result do
    begin
    SplitString(Line, SubscriberId);
    SplitString(Line, Phone);
    SplitString(Line, AreaCodeLen);
    <nog meer SplitString, fucked layout alleen maar op>
    end;
  FSSubscriber.Free;

end;

Zoals je ziet roep ik dus de functie FindIndex aan, die er zo uitziet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function TForm1.FindIndex(const AskedPhoneNumber: String): Integer;
var NewOffset, JumpSize, i: Integer;
    FoundRecord: String;
    Found, Failed: Boolean;


begin
  FSSubscriberIdx:=TFileStream.Create('c:\CDFOON\subphone.idx',fmOpenRead);

  NewOffset:=IndexCount div 2;
  JumpSize:=IndexCount div 4;
  Found:=False;
  Failed:=False;
  if GetPhoneNumber(NewOffset)=AskedPhoneNumber then Found:=True;
  i:=0;
  while not Found do
    begin
    i:=i+1;
    if AskedPhoneNumber>GetPhoneNumber(NewOffset) then
      NewOffset:=NewOffset+JumpSize else

      if AskedPhoneNumber<GetPhoneNumber(NewOffset) then
        NewOffset:=newOffset-JumpSize else

        if AskedPhoneNumber=GetPhoneNumber(NewOffset) then
        Found:=True;
    JumpSize:=JumpSize div 2;
    If JumpSize<1 then JumpSize:=1;
    if i=50 then
      begin
        Found:=True;
        Failed:=True;
      end;

    end;

  if Found then
    Result:=GetOffset(NewOffset);
  if Failed then
    Result:=1;

  FSSubscriberIdx.Free;

end;

In allebei de functies wordt een filestream gebruikt, en die twee wou ik dus allebei hetzelfde noemen. Achteraf gezien heel stom maar ik keek er echt heel erg overheen !!

Mother, will they like this song?


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Op zondag 14 juli 2002 18:16 schreef TheLunatic het volgende:
De exacte error (eigenlijk onnodig overtypewerk lijkt me)

Project ProjectFile.exe raised exception class EAccessViolation with message 'Access violation at address 0044AA08 in module 'ProjectFile.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.
Niet onnodig. Zegt vrij veel zelfs.

Read of address 00000000

Dus je benaderd een nil pointer. Precies wat ook later dus het geval bleek.

Verder 'misbruik' jij FSSubscriberIdx als een soort globale variable in je klasse. Juist vanwege de bug die jij nu had wordt dit gezien als slecht programmeren om globale variablen te gebruiken. Zoiezo 1 varianble voor 2 verschillende dingen gebruiken wordt niet aangeraden :)

We adore chaos because we like to restore order - M.C. Escher


  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Op maandag 15 juli 2002 00:08 schreef TheLunatic het volgende:
Terwijl ik je vraag nummer 2 wil gaan beantwoorden, zie ik ineens wat het probleem is !!

[...]
In allebei de functies wordt een filestream gebruikt, en die twee wou ik dus allebei hetzelfde noemen. Achteraf gezien heel stom maar ik keek er echt heel erg overheen !!
Mooi. Dit bewijst maar weer, dat goed debuggen begint bij het stellen van de juiste vraag. Da's niet om mezelf nu een schouderklopje te geven (daar heb ik anderen voor :)). Debuggen is een vak apart, waarin de onbevooroordeelde blik van een derde weleens heel verhelderend kan werken. Ik debug veel, en die blik van een derde heb ik ook wel eens nodig :)
Pagina: 1