Découper gros fichiers > 4go [Résolu]

Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
- - Dernière réponse : Cirec
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 9 juin 2013 à 16:18
Bonjour,

Je débute sous delphi 5 ( rien de tel pour les bases ) j'ai cherché sur le forum mais rien trouvé de concret pour découper un fichier > 4 go et pouvoir le reconstruire.
J'ai une erreur avec le Tstreamfile. "erreur de vérification d'étendue
ou erreur de flux "
Si vous pouviez me dépanner ...
D'avance merci !
Afficher la suite 

Votre réponse

15 réponses

Meilleure réponse
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
3
Merci
Salut,

[quote=korgis]Mais il me semble que les versions 32 bits de Delphi ne prennent pas en charge les TStream de plus de 2.1 GB.
J'ai bien peur que le problème se situe à ce niveau.../quote

non non le problème ne se situ pas à ce niveau.

Delphi et les Streams gèrent très bien les fichiers plus gros que 4 Go

Le problème de limitation que tu rencontres provient du fait que tu ais choisi le type Integer pour la variable "SizeOfFiles" à la place d'utiliser Int64 dont l'étendue est plus grande.

[quote= l'aide Delphi]Type             Etendue         Format
Integer -2147483648..2147483647 32 bits signé
Int64   -2^63..2^63-1           64 bits signé
/quote
on voit bien que les 2.1 Go de limitation coïncide avec l'étendue du type Integer.

sinon ton code est effectivement juste ... sauf que la progression de la copie ne va pas se voir ... il serait préférable d'opter pour la copie par bloc.

essayes ce code:
function SplitFile(FileName: TFileName; SizeofFiles: Int64; ProgressBar:
  TProgressBar; outputfolder: string): Boolean;
var
  i: Word;
  fs, sStream: TFileStream;
  SplitFileName: string;
  BufferSize: Integer;
begin
  ProgressBar.Position := 0;
  BufferSize := 2048;
  Result := False;
  if outputfolder[length(outputfolder)] <> '\' then
    outputfolder := outputfolder + '\';
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    for i := 1 to Trunc(fs.Size / SizeofFiles) + 1 do
    begin
      SplitFileName := outputfolder + ExtractFileName(FileName) + '.' +
        FormatFloat('000', i);
      sStream := TFileStream.Create(SplitFileName, fmCreate or
        fmShareExclusive);
      try
        repeat
          if fs.Size - fs.Position < BufferSize then
            BufferSize := fs.Size - fs.Position;
          sStream.CopyFrom(fs, BufferSize);
          ProgressBar.Position := Round((fs.Position / fs.Size) * 100);
          Application.ProcessMessages;
        until (sStream.Position >SizeofFiles) or (fs.Size fs.Position);
      finally
        sStream.Free;
      end;
    end;
  finally
    fs.Free;
  end;
  Result := True;
end;


et pour tester:
procedure TForm7.Button1Click(Sender: TObject);
begin
  // $100000000   ==> 4 Go
  // $E0000000    ==> 3.5 Go
  if OpenDialog1.Execute then
    if SplitFile(OpenDialog1.FileName, $E0000000, ProgressBar1,
      ExtractFilePath(OpenDialog1.FileName) + 'Splitt') then
      ShowMessage('Copie Terminée');
end;


Ce code n'est pas parfait ... il ne teste pas si le disque de destination possède suffisamment de place pour effectuer la copie.

Et le répertoire de sortie:
ExtractFilePath(OpenDialog1.FileName) + 'Splitt'


doit déjà exister ... etc.

mais c'est un bon début.

[hr]@+Cirec
[hr]

Merci Cirec 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de Cirec
Messages postés
423
Date d'inscription
samedi 17 mai 2003
Dernière intervention
4 août 2018
3
Merci
@ Cirec:
est ce que D4 est capable d'ouvrir un fichier > 4 Go et d'en renvoyer la taille ?

Ben non.
Une exception est provoquée après l'appel à la méthode "CopyFrom" du Stream :
classe d'exception EReadError avec le message 'Erreur de lecture du flux'

En fait, dans l'unité Classes de D7, un Int64 est passé en paramètre et retourné par CopyFrom :
function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;

alors que dans D4, c'est un LongInt :
function TStream.CopyFrom(Source: TStream; Count: Longint): Longint;

Tout s'explique !

Merci korgis 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de korgis
Messages postés
1293
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
0
Merci
Salut,

Sans ton code, ça risque de ne pas être évident...


Simon
Commenter la réponse de sp40
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
Voici le code

// fonction qui coupe un fichier en plusieurs morceaux avec SizeofFiles qui indique le poids de chaque parties...

function SplitFile(FileName : TFileName; SizeofFiles : Integer; ProgressBar : TProgressBar;outputfolder : String) : Boolean;
var
i : Word;
fs, sStream: TFileStream;
SplitFileName: String;
begin
ProgressBar.Position := 0;
if outputfolder[length(outputfolder)]<>'\' then outputfolder:=outputfolder+'\';
fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
for i := 1 to Trunc(fs.Size / SizeofFiles) + 1 do
begin
SplitFileName := outputfolder+ExtractFileName(FileName)+ '.'+ FormatFloat('000', i);
sStream := TFileStream.Create(SplitFileName, fmCreate or fmShareExclusive);
try
if fs.Size - fs.Position < SizeofFiles then
SizeofFiles := fs.Size - fs.Position;
sStream.CopyFrom(fs, SizeofFiles);
ProgressBar.Position := Round((fs.Position / fs.Size) * 100);
finally
sStream.Free;
end;
end;
finally
fs.Free;
end;
end;



//Ce code provoque erreur sur lecture du flux avec gros fichier > 4 go.
Commenter la réponse de overfun
Messages postés
1293
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
0
Merci
Quelques petites questions complémentaires :
Est-ce que tu as repéré à quel endroit ça plante ? ou à quel moment dans la boucle ?
Quelle valeur donnes tu à SizeOfFiles dans ton appel ? (i étant déclaré en word, si fs.Size / SizeofFiles > 65535, ça va planter)


Simon
Commenter la réponse de sp40
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
J'ai donné à SizeOfFiles la valeur 10240000 (10mo), je ne sait pas exactement ou est le plantage (je testerai ce soir),
tout ce que je peut dire c'est qu'il ne commence meme pas a cree la 1ere partie.
Et effectivement pour le word, je l'est donc remplacé par un cardinal mais le probleme persiste pour les fichiers > 4go.
Commenter la réponse de overfun
Messages postés
1293
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
0
Merci
Essaie de suivre le process en pas à pas et dis moi si tu vois où ça plante.
Est-ce que ça ne peut pas venir de ta machine (trop peu de mémoire ?)

Simon
Commenter la réponse de sp40
Messages postés
423
Date d'inscription
samedi 17 mai 2003
Dernière intervention
4 août 2018
0
Merci
Salut,

Le code est correct.
Mais il me semble que les versions 32 bits de Delphi ne prennent pas en charge les TStream de plus de 2.1 GB.
J'ai bien peur que le problème se situe à ce niveau...
Commenter la réponse de korgis
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
Ok donc voila :

...
SizeofFiles := fs.Size - fs.Position;
showmessage('Test1');
sStream.CopyFrom(fs, SizeofFiles);
showmessage('Test2');
...

Lors de la tentative, Le programme m'affiche ma box "Test1" mais pas "Test2" donc le .CopyFrom(fs, SizeofFiles) provoque l'erreur.


Merci .
Commenter la réponse de overfun
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
Arf ok donc je doit compiler en 64 bits
Commenter la réponse de overfun
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
Donc aucune solution en version 32bits ???
Commenter la réponse de overfun
Messages postés
423
Date d'inscription
samedi 17 mai 2003
Dernière intervention
4 août 2018
0
Merci
Le problème de limitation que tu rencontres provient du fait que tu ais choisi le type Integer pour la variable "SizeOfFiles" à la place d'utiliser Int64 dont l'étendue est plus grande.

Ça c'est sûr.
Et c'est la première chose que j'ai corrigée avant de tester ce code.
Mais j'avais testé sous D4, et... ça ne prend pas. D'où ma réflexion sur "version 32 bits gnagnagna version 64 bits" qui est visiblement à côté.
Car je viens de tester sous D7, et... ça marche.
Reste à savoir ce que ça donne sous D5 : à overfun de nous dire !
Commenter la réponse de korgis
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
0
Merci
@Korgis:

d'après le commentaire d'Overfun:
[quote=Overfun]Ok donc voila :

...
SizeofFiles := fs.Size - fs.Position;
showmessage('Test1');
sStream.CopyFrom(fs, SizeofFiles);
showmessage('Test2');
...

Lors de la tentative, Le programme m'affiche ma box "Test1" mais pas "Test2" donc le .CopyFrom(fs, SizeofFiles) provoque l'erreur.
/quote

on peut en déduire que le TFileStream de D5 ouvre très bien les gros fichiers puisqu'il en retourne la taille ... c'est à partir du CopyFrom que ça pose problème ...

ce à quoi mon code devrait répondre puisqu'il ne transfère que 2048 octets à la fois

as tu testé ma version sous D4 ?

est ce que D4 est capable d'ouvrir un fichier > 4 Go et d'en renvoyer la taille ?

je ne dispose plus de version de Delphi antérieur à D7 d'installé sur ma machine !!

[hr]@+Cirec
[hr]
Commenter la réponse de Cirec
Messages postés
19
Date d'inscription
vendredi 15 mars 2002
Dernière intervention
12 juin 2013
0
Merci
Oui merci en tout cas ça m'aide à mieux comprendre en tout cas sur D5 ça ne marche pas je vais devoir évoluer sur D7 en espérant que mes composants seront bien acceptés.
Commenter la réponse de overfun
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
0
Merci
bon,

si l'erreur se produit sur "CopyFrom" c'est que l'ouverture se fait bien !!!

si le type Int64 est reconnu par D4-D5 alors il reste une solution ... passer directement par les api (CreateFile/ReadFile/SetFilePointer ...)

sinon le plus simple c'est de faire évoluer ta version de Delphi.


[hr]@+Cirec
[hr]
Commenter la réponse de Cirec

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.