Avatar billede jan_h Nybegynder
16. september 2004 - 12:43 Der er 19 kommentarer og
1 løsning

FileStream: Incompatible types: 'string' and 'text'

Har en fejl i nedenstående kode (se spm. titel), det burde være en simpel dum fejl. På forhånd tak..

TCD = RECORD
  Artist      : string[32];
  Titel      : string[32];
  UdgivelsesAar : integer;
end;

var
  frmEksempel: TfrmEksempel;
  CDfil: File of TCD;
  CD: TCD;
  CDarr: array of TCD;
  AntalCD: integer;

implementation

{$R *.DFM}

procedure TfrmEksempel.FormCreate(Sender: TObject);
const
  FileName = 'cder.dat';
var
  fs : TFileStream;
begin
  if FileExists(CDfil) then
    fs := TFileSream.Create(cder.dat, fmOpenWrite)
  else
    fs := TFileStream.Create(cder.dat, fmCreate)
  try
    TCD.Artist := edtArtist.text;
    TCD.Titel := edtTitel.text;

    fs.WriteBuffer(CD, sizeof(TCD));
  finally
    fs.Free;
  end;
end;

end.
Avatar billede jan_h Nybegynder
16. september 2004 - 12:48 #1
Skal siges at jeg ønsker at arrayet skal være dynamisk. Er ikke sikker på om min FormCreate procedure stemmer overens med dette.
Avatar billede martinlind Nybegynder
16. september 2004 - 13:00 #2
din Artist er af typen ShortString og Text er sikker af typen TCaption som er lig en String, prøv at finde en func. til at konvertere en string til short string, er ikke sikker på delphi har en, ellers brug Copy();

/Martin
Avatar billede hrc Mester
16. september 2004 - 13:16 #3
Mht. dit overordnede problem. Kan du ikke bare typecaste den:

  TCD.Artist := string(edtArtist.Text);

Hvis vi antager at du vil føje i enden af filen om den allerede findes så er der er en fejl i din procedure. Når du åbner fmOpenWrite så står Position på nul og det betyder at du overskriver eksisterende data.

Du skal åbne den som du gør, men sæt fs.Seek(soFromEnd) ind bagefter.

procedure TfrmEksempel.FormCreate(Sender: TObject);
const
  FileName = 'cder.dat';
var
  fs : TFileStream;
begin
  if FileExists(CDfil) then
    fs := TFileSream.Create(cder.dat, fmOpenWrite)
  else
    fs := TFileStream.Create(cder.dat, fmCreate); // Glemte også et semikolon her
  try
    fs.Seek(soFromEnd);

    TCD.Artist := string(edtArtist.Text);
    TCD.Titel := string(edtTitel.Text);

    fs.WriteBuffer(CD, SizeOf(TCD));
  finally
    fs.Free;
  end;
end;
Avatar billede jan_h Nybegynder
16. september 2004 - 13:17 #4
const
  FileName = 'cder.dat';

Jeg var åbenbart dum nok til at kalde FileName for FileName i steddet for CDfil!!!
Men nu får jeg en ny fejl meddelelse: Undeclared Identifier: 'TFileStream'
Avatar billede jan_h Nybegynder
16. september 2004 - 13:28 #5
hrc: Hvordan skal jeg erklære min TFileStream i starten af programmet ?
Har prøvet men kan ik rigtig finde ud af korrekt syntaks. :/
Avatar billede jan_h Nybegynder
16. september 2004 - 14:14 #6
Jeg vil gerne give point men jeg skal bare lige have løst mit problem. Med at TFileStream skal erklæres. Det siger den på trods af at jeg har skrevet "hrc"'s kode af.
Avatar billede hrc Mester
16. september 2004 - 14:44 #7
Når der er tale om de "indbyggede" klasser, så er det nemmeste at placere markøren på ordet TFileStream og trykke på F1. Derved kommer hjælpen frem og der kan du se hvilken unit den er defineret i - her er det "Classes" som du skal have føjet til en af de to "uses"-sektioner.

Der er muligt at indsætte uses nedenfor interface- og nedenfor implementation-delen.

unit MyData;

interface

uses
  Classes, SysUtils;

type
  TMyDataForm = class(TForm)
  private
  public
  end;

implementation

uses
  DateUtils, Math;

Hvis du inkluderer den i den øverste uses, så kan du gøre brug af den i TMyForm-klassen. Hvis du sætter den ind efter implementation, så kan du kun definere den lokalt som i eksemplet OnCreate (OnCreate er i øvrigt nok ikke det logiske sted at placere den slags kode.
Avatar billede hrc Mester
16. september 2004 - 14:47 #8
Når jeg skriver "Gøre brug af den i TMyForm-klassen" så mener jeg at du kan lave en, for klassen, global instans. Se det som en pseudo-global variabel som kun klassen kan se.

type
  TMyDataForm = class(TForm)
  private
    fFileStream ::TFileStream; // standard at sætte et "f" foran private "medlemmer"
  public
  end;
Avatar billede jan_h Nybegynder
16. september 2004 - 17:16 #9
hrc:

Nu får jeg en ny fejlmeddelelse! Håber at du stadigvæk er interesseret i at løse alle mine fejl som nok virker meget simple i dine øjne.
Jeg får denne fejl: "Not enough actual parameters" , som refererer til mit "fs.Seek(soFromEnd)". Se forresten lige min kommentar til soFromEnd for er ikke 100% sikker på jeg har forstået det (slog "soFromEnd" op i Delphi Help)

  try
    fs.Seek(soFromEnd) // soFromEnd: Offset skal være mindre eller lig med 0. Da man står ved slutningen af streamen og slut-punktet har værdien 0, må værdien højst være 0 da streamen ikke er større.

    TCD.Artist := edtArtist.text;
    TCD.Titel := edtTitel.text;

    fs.WriteBuffer(CD, sizeof(TCD));
  finally
    fs.Free;
  end;
Avatar billede jan_h Nybegynder
16. september 2004 - 17:17 #10
hrc får points for al den gode hjælp.
Avatar billede jan_h Nybegynder
16. september 2004 - 17:19 #11
ups glemte et semicolon efter fs.Seek ;-) men problemet er der stadigvæk!
Avatar billede jan_h Nybegynder
17. september 2004 - 12:32 #12
fs.Seek(soFromEnd) <- mangler parametre her.
I delphi help angives det således:
function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;

Men jeg ved ikke hvordan jeg skal bruge det korrekt.
Avatar billede hrc Mester
17. september 2004 - 12:35 #13
Undskyld ventetiden. Der manglede lidt parametre, æv. Prøv med

fs.Seek(0,soFromEnd) - det svarer vist i øvrigt til en fs.Seek(fs.Size); hvor man så ikke behøver angive parameter nr. 2
Avatar billede jan_h Nybegynder
17. september 2004 - 12:50 #14
Ok tak.
Får nu en ny fejl: "Object or class type required".

    TCD.Artist := edtArtist.text;
    TCD.Titel := edtTitel.text;


Er det fordi mine strings skal konverteres til short strings som martinlind siger? Hvis ja hvorfor er dette nødvendigt?
Avatar billede martinlind Nybegynder
17. september 2004 - 12:56 #15
fordi en string kan være på 2gb og din string[32] kan kun indeholde 32 chars, så hvis du sætter en shortstring lig med en string, kan det gå grueligt galt
Avatar billede martinlind Nybegynder
17. september 2004 - 12:58 #16
kiggede lige i hjælpen :

When you assign a value to a short-string variable, the string is truncated if it exceeds the maximum length for the type.

så du skriver bare ( hvis det funkede )

TCD.Artist := String(edtArtist.text);
Avatar billede jan_h Nybegynder
17. september 2004 - 14:10 #17
Tak martinlind. Desuden skulle jeg lave en lokal variabel til min record, fordi man ikke må referere direkte til recorden som jeg gør ved TCD.Artist.

Så jeg lavede en lokal variabel kaldet "rec : TCD;" og nu virker det :)
Avatar billede martinlind Nybegynder
17. september 2004 - 14:31 #18
Ja du kan ikke "gemme data" i en Klasse, det er ligesom med en form
Avatar billede jan_h Nybegynder
17. september 2004 - 17:05 #19
hrc, du er vel ikke på msn messenger? kunne godt lige tænke mig at snakke med dig. Min msn messenger passport: janh1984@hotmail.com
Avatar billede hrc Mester
18. september 2004 - 14:00 #20
Jo, du kan prøve hrc_public@.. Havde overset at du forsøgte at tildele til en typedefinition.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester