[Delphi] probleem invoegen bytes in een bestand

Pagina: 1
Acties:
  • 51 views sinds 30-01-2008

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
Hallo, ik was bezig met mijn descent 3 pilot colorizer proggie en nu heb ik een vraag. Ik wil dus bytes gaan toevoegen aan het bestand, alleen niet aan het begin.
VB 2B 00 00 00 3F 4F 5F 6F => 2B 00 00 00 >01 FF FF FF< 3F 4F 5F 6F
Welk commando zou ik hiervoor moeten gebruiken?
Dan nog iets, als ik de onderstaande code (hetgeen wat ik nu heb) dan overschrijft hij de bytes op de plek waar hij moet inserten. Dit is voor nu oke maar hij insert de verkeerde waardes. Namelijk niet de 01 FF 01 01 die ik er wil hebben maar iets anders. Volgens mij ligt het aan het feit dat ik hier gebruik gemaakt heb van Char, hoe zou ik het kunne verhelpen?
(Data = het in te voegen deel)

procedure TForm1.Button3Click(Sender: TObject);
var
handle:thandle;
data:Pchar;
dwwrite:longword;
towrite:longword;
begin

if colordialog1.Execute then
begin
data:=#$01#$FF#$01#$01;
end;
towrite:=4;
handle := CreateFile(Pchar(Label1.caption),GENERIC_WRITE,FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL + FILE_FLAG_RANDOM_ACCESS, 0);
SetFilePointer(handle,3,nil,FILE_BEGIN);
WriteFile(handle,data,towrite,dwwrite,nil);
CloseHandle(handle);
messagebox(0,Pchar('Ok'),Pchar('DONE!!'),0);
end;

end.

Verwijderd

WriteFile(handle,data^,towrite,dwwrite,nil);

Het gaat om het dakje achter data. In Windows.pas staat bij de declaratie van WriteFile namelijk
code:
1
2
function WriteFile(hFile: THandle; const Buffer; nNumberOfBytesToWrite: DWORD;
  var lpNumberOfBytesWritten: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;

Die const zorgt ervoor dat Delphi er zelf een pointer van gaat maken (net als var). Data was al een pointer dus dan zou je een pointer naar een pointer krijgen...

Verwijderd

O ja en inserten doe je natuurlijk door het hele bestand te lezen, bytes weg te schrijven op de gewenste plaats en de rest van het bestand er weer achteraan te schrijven.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
Moet ik hiervoor het bestand opsplitsen? of gewoon tot de bijv 4e byte in lezen daarna mijn deel er achter plakken en daarna de rest er achter zetten?

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
met andere woorden hoe doe je zoiets heb je een link of uitleg site waarop hier wordt in gegaan?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 12:47
Zie de search, dit is al een aantal keer langsgekomen. Toen ging het geloof ik elke keer om PHP (programmeurs van echte programmeertalen zoeken dit soort dingen zelf uit).

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
En je wilt zeker geen kleine hint geven ? over welke functie ik zou moeten gebruiken? (Schrijven, begrijpen doet ik uiteraad zelf)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 12:47
Ik heb al eens wat voorbeelden gegeven van hoe het zou kunnen (net als wat anderen). Hopelijk kun je dat in de search vinden.

In het kort kwam het er op neer dat je de volgende mogelijkheden hebt: (het is nogal beknopt, dus aandachtig lezen ;) )

1. alle data vanaf positie X in het geheugen lezen, op positie X in het bestand nieuwe bytes invoegen, gevolgd door het ingelezen geheugen.

Bestand: ABCDEFGHIJKLMNOP
In te voegen: XXX op positie 3
Stap 1: inlezen DEFGHIJKLMNOP
Stap 2: wegschrijven XXX (Bestand wordt: ABCXXX(...) )
Stap 3: wegschrijven DEFGHIJKLMNOP (Bestand wort: ABCXXX DEFGHIJKLMNOP)

2. hetzelfde, maar dan stukjes van Y bytes inlezen en wegschrijven (waarbij Y bij voorkeur gelijk is aan de grote van het aantal bytes dat je wilt invoegen), om geheugen te besparen. Hierbij open je hebt bestand voor/lezen schrijven (in C met 'R+'), waarbij je in het bestand kan schrijven zonder dat het bestand ingekort wordt. Het verloop van het algoritme is als volgt:

Bestand: ABCDEFGHIJKLMNOP
In te voegen: XXX op positie 3
Stap 1: inlezen DEF
Stap 2: wegschrijven XXX (Bestand wordt: ABCXXXGHIJKLMNOP)
Stap 3: inlezen GHI
Stap 4: wegschrijven DEF (Bestand wordt: ABCXXXDEFJKLMNOP)
Stap 5: inlezen JKL
Stap 6: wegschrijven GHI (Bestand wordt: ABCXXXDEFGHIMNOP)
Stap 7: inlezen MNO
Stap 8: wegschrijven JKL (Bestand wordt: ABCXXXDEFGHIJKLP)
Stap 9: inlezen P
Stap 10: wegschrijve MNO (Bestand wordt: BCXXXDEFGHIJKLMNO)
Stap 11: niets meer in te lezen
Stap 12: wegschrijven P (Bestand wordt: ABCXXXDEFGHIJKLMNOP)

Dit is mijn voorkeursmethode. Als je handig bent maak je er een aparte functie voor, zodat je makkelijk willekeurige stukken data in willekeurige files kunt stoppen. Je hebt hierbij twee buffers nodig van grote Y (waarbij je de 'nieuwe' gegevens als een buffer kan gebruiken).


3. een andere methode naar smaak =)

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
sorry dat ik weer post hoor maar ik bedoelde dus hoe je dat doet in delphi, niet in C of C++ (daar heb ik wel wel hoe je dat ongeveer moet doen)

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 12:47
Op zondag 02 juni 2002 14:00 schreef falcon4ever het volgende:
sorry dat ik weer post hoor maar ik bedoelde dus hoe je dat doet in delphi, niet in C of C++
Ik heb je verteld hoe het moet qua algoritme (ik heb zelfs een imperatieve benadering gebruikt om je op weg te helpen). Aan jou de taak om de stappen uit het algoritme (waar je ook zelf over na mag denken) om te zetten in werkende Delphi code.

Ik ga je uiteraard niet leren programmeren in Delphi. Dan koop je maar een boek (brrr, geld investeren in een hobby!), dan lees je dat (brrr, lezen!), ga je veel oefenenen tot je Delphi beheerst (brrr, oefenen! tijd investeren! zelf dingen uitproberen!) en dan mag je zelf over het probleem nadenken (brrr, nadenken!).

Als je hier niet toe bereidt bent, hoor je naar mijn mening niet te programmeren. Je hoort dan in ieder geval niet op dit forum thuis.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
Laatmaar mensen het is al gelukt

Verwijderd

Op zondag 02 juni 2002 16:35 schreef falcon4ever het volgende:
Laatmaar mensen het is al gelukt
Hoe dan ook, misschien was een TFileStream makkelijker om te gebruiken.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
Nog een probleem hij leest part 2 niet goed in. Weet iemand waarom?


procedure TForm1.Button4Click(Sender: TObject);
var
handle:thandle;
part1:Pchar;
part2:Pchar;
dwwrite:longword;
dwwrite2:longword;
toread:longword;
toread2:longword;
begin
// to read: part 1: 2B 00 00 01 part 2: = the rest
toread:=4;
toread2:=12;
handle := CreateFile(Pchar(Label1.caption),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL + FILE_FLAG_RANDOM_ACCESS, 0);
SetFilePointer(handle,0,nil,FILE_BEGIN);
ReadFile(handle,part1^,toread,dwwrite,nil);

SetFilePointer(handle,0,nil,FILE_BEGIN);
ReadFile(handle,part2^,toread2,dwwrite2,nil);
CloseHandle(handle);

label4.Caption:= part1;
label5.Caption:= part2;

messagebox(0,Pchar('>Check color'),Pchar('N/A'),0);

end;

Verwijderd

Aub, code zo zetten [code]Code[/code], leest wat makkelijker :)

Je doet niet aan error-handling, dus je ziet niet wat fout gaat.

Bij de eerste ReadFile wil je 4 bytes inlezen, en zetten op de locatie waar part1 naar wijst. part1 heb je niet geinitialiseerd, dus je geeft opdracht tot het schrijven naar een waarschijnlijk verboden locatie; hierop volgt een foutmelding.

Bij de tweede ReadFile hetzelfde.

Beter zou zoiets zijn:
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
var
  FileHandle: THandle;
  Buffer: array[0..11] of Char; // alloceer 12 bytes
  Rslt: Integer
  [..]
begin
  [..]
  FileHandle := CreateFile..
  try
    Rslt := SetFilePointer(FileHandle, 0, nil, FILE_BEGIN);
    if Rslt = -1 then
    begin
    ShowMessage('Error1');
    Exit;
    end;
    if not ReadFile(FileHandle, Buffer, toread, dwwrite2, nil) then
    begin
    ShowMessage('Error2');
    Exit;
    end;
    label2.Caption := String(Buffer);
    [..]
  finally
    CloseHandle(FileHandle);
  end;

[edit]
Verhaal een beetje aangepast.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
maar mag ik wel 2x readfile en setfilepointer doen in 1 handle of moet ik ze opsplitsen? (-> ik ga nu de code ff aanpassen...)

anywayz, Thanks!
btw. je bedoelt zeker inlezen ipv schrijven.

edit:
Het is nu gelukt, hij leest nu correct 2 delen in. alleen moet hij eigenlijk het tweede deel lezen tot EOF, toch maar ff verder klooien

Verwijderd

Wat je inleest, moet je ook ergens neer zetten/wegschrijven [in het geheugen]; zo bedoelde ik het.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
op die fiets, ja dat wegschrijven komt nog.
het lukt al aardig :9

Verwijderd

Je weet dat TFileStream een wrapper is om deze functies?

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
euh nee, ik ben nog nieuw in Delphi, en een vriend van me helpt een beetje. Maar echt veel over commando's weet ik niet. Uiteraard kan ik wel even onderzoek doen naar die commando's.

Verwijderd

Om je op weg te helpen, dit is een vb met TFileStream:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var
  Buffer: array[0..1000] of Char;
begin
  with TFileStream.Create(Label1.Caption, fmOpenRead, fmShareDenyWrite) do
  try
    { Ga naar begin van de file, foutmelding als dit mislukt }
    if Seek(0, soFromBeginning) = -1 then
    begin
    ShowMessage('Error1');
    Exit;
    end;
    { Lees 4 bytes, geef foutmelding als er minder dan 4 zijn ingelezen }
    if Read(Buffer, 4) < 4 then
    begin
    ShowMessage('Error2');
    Exit;
    end;
    Label2.Caption := string(Buffer);
  finally
    Free;
  end;
end;

Dus

CreateFile -> TFileStream.Create,
SetFilePointer -> Seek,
ReadFile -> Read,
CloseHandle -> Free.

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
ah ziet er izi uit ja

  • falcon4ever
  • Registratie: Oktober 2001
  • Laatst online: 25-08 23:36
Ik heb nu nog een ander probleem, hieronder zie je het script waarbij ik de filesize (in bytes) ophaal.
Ik wil echter de totale filesize - 4 (bytes) hebben.
Maar zoals ik het nu doe crasht het programma-tje na 4 sec.
(niet direct)
Kan iemand ff checken wat ik verkeerd doe?
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
var
FileHandle: THandle;
Buffer1: array[0..3] of Char; // alloceer 4 bytes
Buffer2: array of Char; //variabele rij (voor 2e deel)
toread2:longword;
nSize: Integer;
strSize: String;
Bytesreken: Integer;
.
. (nog meer variablen maar voor nu geschrapt)


begin
FileHandle := CreateFile(Pchar(Label1.caption),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL + FILE_FLAG_RANDOM_ACCESS, 0);
  try
  
  //Vraag bestands grote op in bytes.
  nSize := GetFileSize (FileHandle, nil);
  SetLength (strSize, 20);
  Str (nSize, strSize);

  //Hier komt het rekendeel, totale bestands grote - 4.
  Bytesreken:= nSize-4;
  toread2:= nSize-4;
  SetLength(Buffer2, Bytesreken); //(Bytesreken moet integer zijn! Buffer 2 moet dus filesize - 4 bytes zijn)
.
.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 28-08 12:00

Janoz

Moderator Devschuur®

!litemod

Sorry. Voordat dit het grote 'geef falcon4ever delphi les' wordt gooi ik hem op slot. Als je met het project waarmee je nu bezig bent zoveel problemen hebt is het mischien een ID om met iets simpelers te beginnen. Dat is leerzamer voor jezelf, en leert je waarschijnlijk ook beter om problemen zelf op te lossen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'

Pagina: 1

Dit topic is gesloten.