2013-05-04 5 views
6

Я загружаю EXE-файл из Интернета с помощью Indy (idHTTP), и я могу использовать memystream или filestream для сохранения его на диск, но я действительно не знаю, есть ли разница между ними (возможно, в структуре результата файла?). Я не мог найти ответа.Delphi - MemoryStream или FileStream

Где, здесь 2 простых функций, чтобы имитировать то, что я делаю:

Function DownloadMS(FUrl, Dest: String): Boolean; 
var 
    Http: TIdHTTP; 
    Strm: TMemoryStream; 
Begin 
    Result := False; 
    Http := TIdHTTP.Create; 
    Strm := TMemoryStream.Create; 
    With Http, Strm Do 
    Try 
    Try 
     Get(FUrl, Strm); 
     If (Size > 0) Then 
     Begin 
     Position := 0; 
     SaveToFile(Dest); 
     Result := True; 
     end; 
    Except 
    end; 
    Finally 
    Strm.Free; 
    Http.Free; 
    end; 
end; 

Function DownloadFS(FUrl, Dest: String): Boolean; 
var 
    Http: TIdHTTP; 
    Strm: TFileStream; 
Begin 
    Result := False; 
    Http := TIdHTTP.Create; 
    Strm := TFileStream.Create(Dest, fmCreate); 
    With Http, Strm Do 
    Try 
    Try 
     Get(FUrl, Strm); 
     Result := (Size > 0); 
    Except 
    end; 
    Finally 
    Strm.Free; 
    Http.Free; 
    end; 
end; 

Что вы по мнению экспертов об использовании одного или другого типа (MemoryStream или FileStream)? Есть ли какая-либо разница в структуре EXE-файла при использовании того или иного типа? Какой тип рекомендуется?

Спасибо! Хороших выходных!

+4

В 'TMemoryStream' использует внутренне' TFileStream' для сохранения в файл (для метода SaveToFile), поэтому ответ довольно прост - используйте 'TFileStream'. – TLama

+0

Я мог подумать о 2 причинах использования TMemoryStream вместо TFileStream. Избегайте очистки в файловой системе в случае исключения и необходимости некоторых манипуляций, прежде чем сохранять ее в файл. – bummi

+6

Ваше бессмысленное использование 'with' заставляет меня бояться. Я бы рекомендовал вам прекратить это делать. –

ответ

5

Нет никакой разницы между TMemoryStream или TFileStream с точки зрения потока.

Они оба потока и содержат поток байтов и оба производны от TStream.

можно реализовать функции обобщается как этот

function DownloadToStream(const AUrl : String; ADest : TStream): Boolean; 
var 
    LHttp: TIdHTTP; 
begin 
    LHttp := TIdHTTP.Create; 
    try 
    LHttp.Get(AUrl, ADest); 
    Result := ADest.Size > 0; 
    finally 
    LHttp.Free; 
    end; 
end; 

и вызвать его с потоком, например TFileStream

var 
    LStream : TStream; 

begin 
    LStream := TFileStream.Create('MyFile.exe', fmCreate); 
    if DownloadToStream('', LStream) then 
    ... 
end; 

или TMemoryStream или что вам нравится

+0

Это действительно то, как код должен быть переупознан. Но я думаю, что речь идет не столько о коде, сколько о дизайне. Если для этой цели используется поток памяти или поток файлов, то это вопрос. –

+1

@DavidHeffernan «Я загружаю ** EXE-файл ** из Интернета ... Есть ли какая-либо разница в структуре ** EXE-файла ** при использовании того или иного типа?» OP задается вопросом, будет ли 'TMemoryStream' хранить данные, отличные от' TFileStream': o) –

+0

Я не читал вопрос таким образом, я полагаю, потому что кажется странным, что любой может подумать, что содержимое потока изменено когда вы храните его на диске, а не в памяти. Это просто странно! –

1

Во многих случаях не будет смысла размещать промежуточный поток памяти между загрузкой и файлом. Все, что будет сделано, - это память, потому что вы должны поместить весь файл в память, прежде чем вы сможете поместить его на диск. Использование файлового потока позволяет избежать этой проблемы.

Основная ситуация, когда проблема с файловым потоком имеет проблемы, заключается в том, что вы хотите быть уверенным, что вы успешно загрузили весь файл перед сохранением на диск. Например, если вы перезаписываете предыдущую версию файла, вы можете загрузить ее, проверить хеш-подпись и только затем перезаписать исходный файл. В этом случае вам необходимо поместить файл в какое-то временное место перед перезаписи. Вы можете использовать поток памяти или использовать поток файлов, используя временное имя файла.

+0

Да, я создаю установщик, и, возможно, пользователь будет обновлять файлы. Поэтому я думаю, что буду использовать MemoryStream, потому что файлы не такие большие (2 или 3 МБ). Спасибо! – Guybrush

+0

@Paruba Вы все равно можете использовать поток файлов, если хотите. Просто используйте временное имя файла. Когда вы счастливы, файл загружен, удалите старый и переименуйте файл temp. –

+9

Использование 'TFileStream' имеет еще одно преимущество - возможность возобновить сломанную загрузку без начала с нуля.Если HTTP-сервер поддерживает диапазоны байтов, вы можете настроить 'TIdHTTP', чтобы сообщить серверу, какую часть удаленного файла отправить, а не весь файл. Для небольших файлов это не имеет большого значения, но для больших файлов это может даже возможность загружать разные разделы одного и того же файла с использованием нескольких потоков за один раз. –