Probleme mit eigener Kopierroutine

Für allgemeine Fragen zur Programmierung mit PureBasic.
Agent
Beiträge: 296
Registriert: 13.09.2004 11:28
Kontaktdaten:

Beitrag von Agent »

Spielt aber keine Rolle. Die Routine bleibt beim 1. READDATA hängen. Der Callback kommt danach erst.
Agent_Sasori
It's not a bug - it's a feature!
http://www.StephenKalisch.de | http://www.ria-tec.com | http://www.dirsync.de
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

Gut, dass du es ohne Callback ausprobiert hast, weil ich wette dann funktioniert es.

Probier es mal mit Prototype anstatt diesem CallFunction-Gepfriemel, welches man eh nicht mehr nehmen sollte.
So in etwa:

Code: Alles auswählen

Prototype MyProgressRoutine(Pos.q, Length.q)

Procedure SK_CopyFile(sourcefile$, targetfile$, OverwriteExistingFile.b=#True, ProgressRoutine.MyProgressRoutine=0, qPackSize.q=0)
 
  ; Definitionen
  Protected qSourceFileLen.q, qSourceFilePos.q
  Protected *CopyBuffer, qDataReaded.q
  Protected lSourceFile.l, lTargetFile.l, lResult.l
  Protected Memory.MEMORYSTATUS

  ; Rückgabe-Codes definieren
  #SK_CopyFile_Failed             = 0 ; #False
  #SK_CopyFile_OK                 = 1 ; #True
  #SK_CopyFile_0ByteFile          = 2 ; Quell-Datei ist 0 Byte groß
  #SK_CopyFile_UserAbort          = -1 ; User hat abgebrochen
  #SK_CopyFile_FileNotFound       = -2 ; Quell-Datei nicht gefunden
  #SK_CopyFile_CannotOpenSource   = -3 ; Konnte Quelle nicht öffnen
  #SK_CopyFile_CannotCreateTarget = -4 ; Konnte Zieldatei nicht anlegen
  #SK_CopyFile_TargetCorrupt      = -5 ; Source-Size und Target-Size sind unterschiedlich. Ggf, Speicher voll.
  #SK_CopyFile_MemoryError        = -6 ; Konnte Speicher nicht reservieren
 
  ; Standard-Wert für Rückgabe: Fehler!
  lResult=#SK_CopyFile_Failed


  ; Progress-Routine (Aufbaubeispiel)
        ; Procedure SK_CopyFile_ProgressCallback(act_pos.q, filesize.q)
        ;   If filesize>0
        ;     percentage_done = (act_pos*100)/filesize
        ;   Else
        ;     percentage_done = 100
        ;   EndIf
        ;   SetGadgetState(#main_progressbar_file, percentage_done)
        ; EndProcedure
 
  ; Gibt es Zieldatei schon: User fragen wie es weiter gehen soll!
  If FileSize(targetfile$)>0 And OverwriteExistingFile=#False ; Ziel existiert, User will gefragt werden!
    If MessageRequester("","Möchten Sie folgende Datei überschreiben?"+#CRLF$+#CRLF$+targetfile$, #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
      ProcedureReturn #SK_CopyFile_UserAbort
    EndIf     
  EndIf
 
  ; Quelle öffnen
  lSourceFile = OpenFile(#PB_Any, sourcefile$)   
  qSourceFilePos = 0
   
  If IsFile(lSourceFile) ; Quelle öffnen ok?
   
    ; Zieldatei erzeugen
    lTargetFile = CreateFile(#PB_Any, targetfile$)
   
    If IsFile(lTargetFile) ; Ziel öffnen ok?
     
      ; Wieviel arbeit liegt vor uns
      qSourceFileLen=Lof(lSourceFile) ; Dateigröße ermitteln
     
      If qSourceFileLen > 0 ; Quelle eine 0-Byte-Datei?
       
        ; Paketgröße ermitteln
        If qPackSize = 0 ; Dynamische Paketgröße             
          GlobalMemoryStatus_(Memory.MEMORYSTATUS)
          If qSourceFileLen < 3145728 ; 3 MB
            qPackSize = qSourceFileLen
          ElseIf (qSourceFileLen/100) < (Memory\dwAvailPhys / 4)
            qPackSize = qSourceFileLen / 100
          Else
            qPackSize = (Memory\dwAvailPhys / 1000)
          EndIf
        EndIf
       
        ; Falls ProgressCallback: Startwert eintragen, damit User sieht es passiert was
        If ProgressRoutine
          ProgressRoutine(1, qSourceFileLen)
        EndIf

        ; Speicher reservieren für Blocks...
        *CopyBuffer = AllocateMemory(qPackSize)
       
        If *CopyBuffer ; Speicher ok? Dann los!
       
          Repeat
           
            ; Daten aus Quelle einlesen
            qDataReaded = ReadData(lSourceFile, *CopyBuffer, qPackSize)
           
            If qDataReaded > 0 ; Daten korrekt gelesen? Dann ab in die Zieldatei
              WriteData(lTargetFile, *CopyBuffer, qDataReaded)               
              qSourceFilePos + qDataReaded               
            ElseIf qDataReaded = 0 And qSourceFilePos < qSourceFileLen ; Ui, da ging was schief
              lResult = #SK_CopyFile_Failed
            EndIf
         
            ; Progress aktualisieren
            If ProgressRoutine And (qDataReaded > 0) And (qSourceFilePos < qSourceFileLen)
              ProgressRoutine(qSourceFilePos, qSourceFileLen)
            EndIf
           
          Until qSourceFilePos >= qSourceFileLen Or qDataReaded=0 Or bGlobalAbort=#True Or bMainExit=#True
   
          If bGlobalAbort = #True ; Hat User abgebrochen?
            lResult = #SK_CopyFile_UserAbort
          EndIf
         
          If qSourceFileLen <> qSourceFilePos ; Gibts Probleme mit den Dateigrößen? Differenzen?
            lResult = #SK_CopyFile_TargetCorrupt
            Debug "Source <> Target"
          EndIf
                     
          ; Speicher wieder freigeben!
          FreeMemory(*CopyBuffer)
         
        Else
          lResult = #SK_CopyFile_MemoryError ; Probleme beim Speicher reservieren
        EndIf
       
      Else
        lResult = #SK_CopyFile_0ByteFile ; War ne 0-Byte-Datei
      EndIf
     
      ; Zieldatei wieder schließen
      CloseFile(lTargetFile)

    Else
      lResult = #SK_CopyFile_CannotCreateTarget ; Zieldatei konnte nicht angelegt werden
    EndIf
   
    ; Quelldatei wieder schließen
    CloseFile(lSourceFile)     
         
    ; Datum und Attribute wie Originaldatei setzen
    SetFileDate(targetfile$, #PB_Date_Created, AddDate(GetFileDate(sourcefile$, #PB_Date_Created), #PB_Date_Hour, UTC_Korrektur))
    SetFileDate(targetfile$, #PB_Date_Modified, AddDate(GetFileDate(sourcefile$, #PB_Date_Modified), #PB_Date_Hour, UTC_Korrektur) )     
    SetFileAttributes(targetfile$, GetFileAttributes(sourcefile$)) ; Attribute angleichen

    ; Progress lieber nochmal auf 100% setzen
    If ProgressRoutine
      ProgressRoutine(qSourceFileLen, qSourceFileLen)
    EndIf
       
    lResult = #SK_CopyFile_OK ; Super, alles ok
  Else
 
    lResult = #SK_CopyFile_CannotOpenSource ; Quelle konnte nicht geöffnet werden :(
  EndIf
   
  ProcedureReturn lResult
EndProcedure
Agent
Beiträge: 296
Registriert: 13.09.2004 11:28
Kontaktdaten:

Beitrag von Agent »

Was soll das ändern? Es liegt wohl eindeutig am ReadData() oder?
Agent_Sasori
It's not a bug - it's a feature!
http://www.StephenKalisch.de | http://www.ria-tec.com | http://www.dirsync.de
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

Agent hat geschrieben:Was soll das ändern? Es liegt wohl eindeutig am ReadData() oder?
Nein liegt es nicht!
Aber ist mir jetzt auch wurscht.

Kleiner Tipp am Rande noch auch wenns bei dir bestimmt nicht ankommt:
CallFunctionFast kann nicht mit QUADs als Parameter umgehen (steht sogar in der Hilfe).
Agent
Beiträge: 296
Registriert: 13.09.2004 11:28
Kontaktdaten:

Beitrag von Agent »

Also gut.
Ich bin dabei auf Prototypes umzustellen. Grundsätzlich läuft die Sache. @HeXOR: Danke.

Bei der Adressierung hab ich wohl noch einen Denkfehler:

ich möchte die Callback-Procedure flexibel angeben können, da die Kopierroutine eine Include-Datei ist. Nun folgendes:

Definition wie folgt:

Code: Alles auswählen

Prototype.l SK_CopyFile_ProgessCallback(act_pos.q, filesize.q)
Das der Aufbau der Kopierroutine. Hier ist *ProgressCallback zu sehen.

Code: Alles auswählen

Procedure SK_CopyFile(sourcefile$, targetfile$, *ProgressCallback.l=0, OverwriteExistingFile.b=#True, lBufferSize.l=#False)

CopyFile_Progess.SK_CopyFile_ProgessCallback = @*ProgressCallback

...

EndProcedure
PB meldet beim Kompilen keinen Fehler, aber beim Ausführen ein
Invalid memory access
Aufgerufen habe ich die Kopierroutine wie folgt:

Code: Alles auswählen

copysuccess.b=SK_CopyFile(CopyList()\entryname$, targetfile$, @SK_CopyFile_ProgressCallback())
Kann mir jemand auf die Sprünge helfen mit der Adressierung?
Mit einer CallFunctionFast() ging das so. Bei Prototypes wohl nicht mehr.

Vielen Dank im vorraus!
Agent_Sasori
It's not a bug - it's a feature!
http://www.StephenKalisch.de | http://www.ria-tec.com | http://www.dirsync.de
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

O.k., ich hab wahrscheinlich eine masochistische Ader... ;)

Da du bereits die Adresse deiner Prozedur übergibst, wäre es so richtig:

Code: Alles auswählen

CopyFile_Progess.SK_CopyFile_ProgessCallback = *ProgressCallback
Mit @*ProgressCallback würdest du die Adresse deiner ProgressCallback-Variable bekommen, was dich ja bestimmt nicht wirklich interessiert.

Allerdings sehe ich den tieferen Sinn nicht, wieso machst du es nicht wie ich oben (oder hast du meinen Code etwa nicht einmal genauer angeschaut ? *ts ts ts*) ?
Wozu die Adresse nochmal weiterreichen, wenn du sie doch gleich in die richtige Pseudotyp-Variable Bild kannst ?
schleicher
Beiträge: 214
Registriert: 30.03.2014 19:57
Computerausstattung: Purebasic 5.70
Wohnort: 18314 Löbnitz

Re: Probleme mit eigener Kopierroutine

Beitrag von schleicher »

Das hier ist zwar schon sehr alt, aber ich würde es gern nutzen, da diese Kopierfunktion mit Progress_Anzeige ist.
Wie müsste dann der Kopierbefehl aussehen ? So?

Code: Alles auswählen

SK_CopyFile(sourcefile$, targetfile$, 1, 1, 1)
Ganz verstehe ich nicht, wie die Progressbar den akt.Pos. _ Wert bekommt, denn mit

Code: Alles auswählen

Prototype MyProgressRoutine(Pos.q, Length.q)
kann ich als Anfänger nicht so richtig was anfangen Übergibt Prototype die Werte automatisch an die Procedure SK_CopyFile_ProgressCallback(act_pos.q, filesize.q) ?
(Die Procedure : SK_CopyFile_ProgressCallback(act_pos.q, filesize.q) habe ich erstellt so wie es im Beispiel angegeben war.
Purebasic 5.51
Antworten