Kopiowanie danych między strumieniami

0

Przykładowy nagłówek:

function ProcessData(const Source: TStream; Traget: TStream);

Funkcja ma skopiować wyznaczoną część Source do Target:

Target.CopyFrom(Source, 0);

Jednakże ta metoda sprawdza się tylko dla małych strumieni (2-3MB), gdyż dla większych kopiowanie jest niesamowicie wolne (dla ~12MB ok. 2.5 sekundy !!!). Istnieje sposób szybko przenieść część strumienia do innego?

0

Może tak:

procedure KopiujStrumienie(const ZKtorego: TStream; var DoKtorego: TStream);

Jeżeli zrobiłbyś tak:

function KopiujStrumienie(ZKtorego: TStream): TStream;

To program musiałby skopiować całą zawartość streamu ZKtorego do instancji w funkcji KopiujStrumienie, funkcja skopiowałaby zawartość do Result, a potem z Resulta trzeba byłoby skopiować instancję do miejsca, z którego funkcja była wywoływana (czyli zamiast jednego kopiowania - aż 3).

W pierwszym nagłówku jest przekazywany tylko wskaźnik do zmiennej ZKtorego, a jako wyjście wskaźnik do zmiennej DoKtorego. const i var różnią się tym, że zmiennej opatrzonej przez const nie można edytować w danej procedurze. Operacje na zmiennych ZKtorego i DoKtorego byłyby skierowane do wskaźnika, a ten wskazuje miejsce w pamięci, gdzie przechowywane są strumienie.

0

Ale jak kopiować? Przez CopyFrom, czy jak?

0

Mam nadzieję, że zrozumiałem Twój pierwszy post.

Chodziło mi o nagłówek funkcji, który 3 razy spowalniał kopiowanie strumieni.

0
mnbvcX napisał(a)

Może tak:

procedure KopiujStrumienie(const ZKtorego: TStream; var DoKtorego: TStream);

Jeżeli zrobiłbyś tak:

function KopiujStrumienie(ZKtorego: TStream): TStream;

To program musiałby skopiować całą zawartość streamu ZKtorego do instancji w funkcji KopiujStrumienie, funkcja skopiowałaby zawartość do Result, a potem z Resulta trzeba byłoby skopiować instancję do miejsca, z którego funkcja była wywoływana (czyli zamiast jednego kopiowania - aż 3).

W pierwszym nagłówku jest przekazywany tylko wskaźnik do zmiennej ZKtorego, a jako wyjście wskaźnik do zmiennej DoKtorego. const i var różnią się tym, że zmiennej opatrzonej przez const nie można edytować w danej procedurze. Operacje na zmiennych ZKtorego i DoKtorego byłyby skierowane do wskaźnika, a ten wskazuje miejsce w pamięci, gdzie przechowywane są strumienie.

guzik prawda - ZKtorego i DoKtorego i ew. Result to tylko wskaźniki i czy dasz var, const, out czy coś innego to jeden h*

vt jak otwierasz strumienie przekazane do tej funkcji??

0
Misiekd napisał(a)

vt jak otwierasz strumienie przekazane do tej funkcji??

...
function StreamProcess(const Source: TStream; var Target: Tstream): Boolean;
begin
...
Target.CopyFrom(Source, 0);  // <-- określony fragment strumienia się kopiuje, ale jak dużo tego jest to trwa nieakceptowalnie długo
...
end;
...
var
  Source, Target: TFileStream;
begin
...
  Source := TFileStream.Create(...);
  Target := TMemoryStream.Create(...);
  if StreamProcess(Source, Target) then
    ...
end;
....

Funkcje nie tworzy oczywiście nowego strumienia, tylko operuje na tym co dostała. Samo działanie na nim jest proste i szybkie, bo to jest Seek() i czytanie kilku bajtów. W zależności co odczyta kopiuje do drugiego strumienia te dane. To właśnie CopyFrom wlecze się przy "dużych" danych (zwolnienie widać już przy 4-5 MB, testowałem maksymalnie na 12 MB).

0

czemu masz Target := TMemoryStream.Create(...); skoro Target: TFileStream; ?

0
Misiekd napisał(a)

czemu masz Target := TMemoryStream.Create(...); skoro Target: TFileStream; ?

Source: TFileStream;
Target: TMemoryStream;

;-P

Ale co z tym przenoszeniem danych [glowa]

0

Po kolejnym teście okazało się, że kopiowanie między strumieniamu tego samego typu jest sprawne (np. TFileStream --> TFileStream), natomiast przy różnych typach nie [glowa]

Czyli funkcja ładująca dane z pliku jest dobra, natomiast problem jest przy jej wywoływaniu. Jakich zatem użyć typów, aby szybko załadować część pliku i przekazać go dalej?

1 użytkowników online, w tym zalogowanych: 0, gości: 1