Професионална програма
Loading...
+ Нов въпрос
Elena123456 avatar Elena123456 200 Точки

4. Copy Binary File- solution with buffer and another with CopyTo

Здравейте,

задачата е  № 4 от тук- https://softuni.bg/trainings/resources/officedocument/52728/streams-files-and-directories-exercise-csharp-advanced-september-2020/3007

Ще бъда много благодарна, ако някой погледне двете ми решения и потвърди дали са абсолютно взаимозаменяеми- едното е с използването на буфер, а другото е директно с копиране.

Решението без буфер- https://pastebin.com/HMt1aNva

Решението с буфер- https://pastebin.com/K9zB1nX6

На пръв поглед резултата и при двете е еднакъв. Абсолютно заменяеми ли са и има ли случай, в който е за предпочитане да използвам решението, което е с буфер?

 

Тагове:
0
C# Advanced
MartinBG avatar MartinBG 3828 Точки
Best Answer

В решението с буфер има бъг на ред №22:

writer.Write(buffer, 0, buffer.Length);

Трябва да е:

writer.Write(buffer, 0, bytesRead);

Може да се запише и така:

int bytesRead;

while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0)
{
   writer.Write(buffer, 0, bytesRead);
}

Иначе, двете решения са функционално еквивалентни.

Основната причина да се използва буфериране е, че получаването или изпращането на (примерно) 1000 байта не е много по-бавно от това на 1 байт (т.е. 1000 операции по 1 байт ще са много пъти по-бавни от 1 операция с 1000 байта).

 

 

Сега погледнах спецификацията на CopyTo метода и изглежда, че и той използва буфериране. По подразбиране размерът на буфера е 81920 байта, но методът има овърлоуднат вариант, при който размерът на буфера може да бъде указан изрично.

При наличието на подобен помощен метод, създаването на собствен буфер и използването на Read + Write методите за копиране изглежда излишно и е оправдано само ако искаме да модифицираме или да анализираме прочетените данни, преди да ги запишем на новото място.

 

2
18/01/2021 01:34:48
Elena123456 avatar Elena123456 200 Точки

Благодаря за отговора и за  открития бъг. smiley

Досега не успявах да разбера задачите с използването на буфер и докато се опитвах да избегна използването му се натъкнах случайно на "CopyTo". Предполагам, че ще свърши работа дори и при разцепването на файл на еднакви парчета, като можем да му променяме размера на буфера.

След като видях вашия запис с използването на буфер, вече разбрах какво се казва на програмата- "чети с размера на буфера, но ако не можеш накрая да четеш с размера на буфера, чети колкото байтове остават. Винаги, колкото байтове прочетеш от единия файл, запиши ги в другия файл. И няма логика в другия файл да записваме bufer.length, защото съвсем накрая може да са прочетени доста по-малко байтове".

Като дете съм виждала грамофон и четенето с буфер ми напомня на него- главата му се движи по плочата с една и съща скорост (с един и същи буфер) и накрая чете колкото остава преди да свърши песента. Така трябва да е и тук, нали? Но за жалост и една песен на грамофон не си спомням. smiley

Още веднъж много благодаря за разяснението.

Поздрави!

1
MartinBG avatar MartinBG 3828 Точки

Да, CopyTo е по-добрият вариант за копиране на данни от един поток/файл в друг, защото премахва нуждата от ръчно менажиране на буфера.

Да, в буфера се четат колкото се може повече байтове (до размера на буфера или колкото има останали във входящия поток) и  като резултат се връща размера на реално прочетените байтове.

1
Elena123456 avatar Elena123456 200 Точки

Извинявам се много, но имам само още едно питане отностно работата с буфери, преди да ги завърша.

На лекция ни е показано това решение за разцепването на един файл на четири еднакви парчета- https://pastebin.com/ykAJFdFj , но виждам, че отново при писането в останалите четири файла е използвана дължината на буфера( buffer.Length ), а не прочетените байтове(bufferRead). Допълнително има една проверка:

  • if (bytesRead < buffer.Length)

                {

                    buffer = buffer.Take(bytesRead).ToArray();

                }

  Въпроса ми е дали е едно и също, ако махна горната проверка и коригирам последния ред- винаги да се изписват точно прочетените байтове във всеки един от четирите файла- " currentPartStream.Write(buffer, 0, bufferRead) ", вместо-   "currentPartStream.Write(buffer, 0, buffer.Length) ". Това решение би ли дало бъг, който не е явен в тази задача? Питам понеже няма Judge за задачата и ми е малко трудно все още да я тествам.

0
20/01/2021 00:20:07