Découper gros fichiers > 4go

Résolu
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013 - 7 juin 2013 à 09:21
 Pappy - 9 févr. 2020 à 16:30
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 !

15 réponses

Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
7 juin 2013 à 23:18
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]
3
manque le signe = à la ligne 29
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
8 juin 2013 à 17:39
@ 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 !
3
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 juin 2013 à 11:36
Salut,

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


Simon
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
7 juin 2013 à 14:16
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 juin 2013 à 14:48
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
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
7 juin 2013 à 15:39
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.
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 juin 2013 à 15:45
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
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
7 juin 2013 à 16:57
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...
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
7 juin 2013 à 17:06
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 .
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
7 juin 2013 à 17:07
Arf ok donc je doit compiler en 64 bits
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
7 juin 2013 à 17:23
Donc aucune solution en version 32bits ???
0
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
8 juin 2013 à 09:48
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 !
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
8 juin 2013 à 13:41
@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]
0
overfun Messages postés 19 Date d'inscription vendredi 15 mars 2002 Statut Membre Dernière intervention 12 juin 2013
8 juin 2013 à 17:54
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.
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
9 juin 2013 à 16:18
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]
0
Rejoignez-nous