Bueno, sigo con el tema. Ahora que se que alguien lo lee
Vamos a sacrificar un poco de rapidez a cambio de ganar sencillez, y evitar además tener que guardar una imagen del disco. Ahora leemos directamente la información del disco y la analizamos, todo en memoria.
Código Delphi
[-]
program recover;
{$APPTYPE CONSOLE}
uses Windows, SysUtils, Classes;
const
ClusterSize = 512;
procedure Intento(Origen: TStream; FormatStr: String; var Index: Integer);
var
Destino: TMemoryStream;
Buffer: array[0..$FFFF] of Byte;
Header: array[1..4] of Byte;
Size: Integer;
begin
Destino:= TMemoryStream.Create;
try
Header[1]:= $FF; Header[2]:= $D8;
Destino.WriteBuffer(Header,2);
while TRUE do
begin
Origen.ReadBuffer(Header,4);
Size:= ((Header[3] shl 8) + Header[4]) - 2;
case Header[2] of
$01,$D0..$D8: begin
Destino.WriteBuffer(Header,2);
Origen.Seek(-2,soFromCurrent);
end;
$D9: begin
Destino.WriteBuffer(Header,2);
Destino.SaveToFile(Format(FormatStr,[Index]));
Writeln('Recuperada: ' + Format(FormatStr,[Index]));
inc(Index);
Exit;
end;
$DA: begin
Destino.WriteBuffer(Header,2);
Origen.Seek(-2,soFromCurrent);
while TRUE do
begin
Origen.ReadBuffer(Buffer,1);
if Buffer[0] = $FF then
begin
Origen.ReadBuffer(Buffer,1);
if (Buffer[0] <> 0) and not (Buffer[0] in [$D0..$D7]) then
begin
Origen.Seek(-2,soFromCurrent);
break;
end else
begin
Header[1]:= $FF;
Header[2]:= Buffer[0];
Destino.WriteBuffer(Header,2);
end;
end else
Destino.WriteBuffer(Buffer,1);
end;
end
else
begin
Origen.ReadBuffer(Buffer,Size);
Destino.WriteBuffer(Header,4);
Destino.WriteBuffer(Buffer,Size);
end;
end;
end;
finally
Destino.Free;
end;
end;
procedure Scan(Stream: TStream; FormatStr: String);
var
Buffer: PChar;
Indice: Integer;
Leidos: Integer;
MemStream: TMemoryStream;
Posicion: int64;
begin
Indice:= 0;
GetMem(Buffer,ClusterSize);
try
Leidos:= Stream.Read(Buffer^,ClusterSize);
while Leidos > 0 do
begin
if CompareMem(Buffer,PChar(#$FF#$D8#$FF),3) then
begin
Posicion:= Stream.Position;
try
MemStream:= TMemoryStream.Create;
try
MemStream.Write(Buffer[2],Leidos - 2);
MemStream.CopyFrom(Stream,8*1024*1024);
MemStream.Position:= 0;
Writeln('Encontrada una posible imagen.');
Intento(MemStream,FormatStr,Indice);
finally
MemStream.Free;
end;
except
On E: Exception do
Writeln('Error: ' + E.Message);
end;
Stream.Position:= Posicion + ClusterSize;
end;
Leidos:= Stream.Read(Buffer^,ClusterSize);
end;
finally
FreeMem(Buffer);
end;
end;
var
Stream: TFileStream;
Marca: TDateTime;
begin
try
if ParamCount = 2 then
begin
TFileStream.Create(Format(ParamStr(2),[0]),fmCreate).Free;
DeleteFile(Format(ParamStr(2),[0]));
Stream:= TFileStream.Create(ParamStr(1),fmOpenRead or fmShareDenyNone);
try
Marca:= Now;
Scan(Stream,ParamStr(2));
Writeln('Tiempo transcurrido: ' + TimeToStr(Now-Marca));
finally
Stream.Free;
end;
end else
Writeln('Help: ' + ExtractFilename(ParamStr(0)) + ' ');
except
On E: Exception do
Writeln('Error: ' + E.Message);
end;
end.
Por ejemplo:
Código:
recover \\.\F: c:\temp\%d.jpg
Tarda un poco en realizar el análisis de todo el disco, por ejemplo, para un disco de Usb de 128 Megas tarda unos 5 Minutos. Aunque puede que sea menos si el dispositivo es rápido, y ajustamos mejor el tamaño del cluster.