Скопируйте файл небольшими порциями

Я хочу скопировать файл небольшими порциями (чтобы отменить операцию копирования, если это необходимо).

Я пытаюсь следовать немаркированному решению здесь: copy">Как скопировать файл с возможностью отмены копирования?

Но я получаю файл 0 байт

Что я делаю неправильно?

Public Class Form1

   Dim cancelled As Boolean = Nothing
   Dim input = New System.IO.FileStream("C:\1.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)
   Dim output = New System.IO.FileStream("C:\Nueva carpeta\1.txt", System.IO.FileMode.CreateNew, System.IO.FileAccess.Write, System.IO.FileShare.Write)

   Public Sub CopyStream(ByVal inputStream As System.IO.Stream, ByVal outputStream As System.IO.Stream)
       'Dim buffer = System.IO.File.ReadAllBytes("C:\1.txt")

       Dim buffer = New Byte((1024) - 1) {}
       Dim bytesRead As Integer = 1

       While (inputStream.Read(buffer, 0, buffer.Length) > 0)
           outputStream.Write(buffer, 0, bytesRead)
           'bytesRead += 1

           If cancelled Then
               MsgBox("operacion cancelada")
               Return
           End If
       End While

       inputStream.Close()
       outputStream.Close()
       MsgBox("operacion terminada")

   End Sub

   Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
       CopyStream(input, output)
   End Sub

End Class

**

ОБНОВЛЕНИЕ 1:

**

Я попытался выполнить шаги ответа Virtlink и добавить недостающие части в исходный код, но все равно получаю файл с нулевым байтом.

> Public Class Form1

    Dim input = New System.IO.FileStream("C:\Test.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)
    Dim output = New System.IO.FileStream("C:\Test_New.txt", System.IO.FileMode.CreateNew, System.IO.FileAccess.Write, System.IO.FileShare.Write)

    Public Sub CopyStream(ByVal inputStream As System.IO.Stream, ByVal outputStream As System.IO.Stream)

        Dim buffer = New Byte(1024) {}
        Dim bytesRead As Integer

        ' Read some bytes
        While (bytesRead = inputStream.Read(buffer, 0, buffer.Length) > 0)
            ' Write them to the output
            outputStream.Write(buffer, 0, bytesRead)
        End While

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CopyStream(input, output)
    End Sub

End Class

**

ОБНОВЛЕНИЕ 2:

**

МОЯ ПОСЛЕДНЯЯ НЕУДАЧНАЯ ПОПЫТКА:

    Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim input_filepath As String = "C:\Test.txt", output_filepath As String = "C:\Test_New.txt"

        Dim input = New System.IO.FileStream(input_filepath, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite)
        Dim output = New System.IO.FileStream(output_filepath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)

        CopyStream(input, output)

        ' For Testing:
        If New IO.FileInfo(output_filepath).Length = 0 Then IO.File.Delete(output_filepath) : Application.Exit() Else Process.Start("Notepad", output_filepath)

    End Sub

    Public Sub CopyStream(ByVal inputStream As System.IO.Stream, ByVal outputStream As System.IO.Stream)

        Dim buffer = New Byte(1024) {}, bytesRead As Integer

        While ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
            outputStream.Write(buffer, 0, bytesRead)
        End While

        inputStream.Flush() : outputStream.Flush()
        inputStream.Close() : outputStream.Close()

    End Sub

End Class

**

ОБНОВЛЕНИЕ 3:

**

РЕШЕНИЕ

Проблема была в VB.NET. Я не могу присвоить значение переменной в условии цикла, так что это рабочий Sub:

  Public Sub CopyStream(ByVal inputStream As Stream, ByVal outputStream As Stream)

    Dim buffer = New Byte(1025) {}
    Dim bytesRead As Integer = 0

    Do
        bytesRead = inputStream.Read(buffer, 0, buffer.Length)
        If bytesRead > 0 Then
            outputStream.Write(buffer, 0, bytesRead)
        End If
    Loop While (bytesRead > 0)

    outputStream.Flush()
    inputStream.Close() : outputStream.Close()

End Sub

person ElektroStudios    schedule 21.03.2013    source источник
comment
вы пытаетесь прочитать байты длины буфера, а затем записать только один. Это явно не правильный код.   -  person Mitch Wheat    schedule 21.03.2013
comment
Вот почему я задал вопрос, потому что я не знаю, как правильно это сделать, но, по крайней мере, я искал и пробовал, прежде чем спрашивать, если вы действительно думаете, что я заслуживаю отрицательного голоса и закрытия. .. в любом случае спасибо за комментарий.   -  person ElektroStudios    schedule 21.03.2013
comment
Вы неправильно перевели строки кода, на которые ссылаетесь. Я предлагаю посмотреть на этот код еще раз.   -  person Mitch Wheat    schedule 21.03.2013
comment
Я использовал 2 онлайн-переводчика и не могу перевести лучше, потому что не знаю синтаксиса C#. Но я еще раз взгляну на код. PS: извините за мой английский   -  person ElektroStudios    schedule 21.03.2013
comment
Я не могу поверить в причину закрытия. Не вопрос, спасибо за исчерпывающую информацию, ребята...   -  person ElektroStudios    schedule 21.03.2013
comment
Просто быстрый комментарий: похоже, вам нужно добавить: bytesRead = перед inputStream.Read(buffer, 0, buffer.Length) > 0.   -  person ispiro    schedule 21.03.2013


Ответы (1)


Вы должны понимать, что вы делаете и как это работает.

Во-первых, вы выделяете буфер.

Dim buffer = New Byte(1024) {}

Затем вы идете и читаете некоторые данные из входного потока. Данные помещаются в buffer, начиная с 0, максимум buffer.Length байт. Метод возвращает количество байтов, которые он фактически прочитал и поместил в буфер.

bytesRead = inputStream.Read(buffer, 0, buffer.Length)

Если число прочитанных вами байтов больше 0, значит, вы еще не достигли конца файла.

While (bytesRead > 0)

Затем вы записываете в выходной поток ровно те байты, которые были прочитаны (bytesRead байт). Запишите байты из buffer, начните с индекса 0 и запишите bytesRead количество байтов.

outputStream.Write(buffer, 0, bytesRead)

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

outputStream.Flush()
outputStream.Close()

Собираем вместе:

Dim buffer = New Byte(1024) {}
Dim bytesRead As Integer

' Read some bytes
While ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
    ' Write them to the output
    outputStream.Write(buffer, 0, bytesRead)

    If cancelled Then
        MsgBox("operacion cancelada")
        Return
    End If

    ' Repeat
End

outputStream.Flush()
outputStream.Close()

В последний раз я писал VB более десяти лет назад. Вы должны убедиться, что синтаксис правильный.


Обратите внимание, как исходный код содержит эту строку:

While ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)

Вы видите часть bytesRead =? Вы не скопировали это в свой код. Важно хранить количество прочитанных байтов.


Окончательный код: это работает на моем компьютере:

Imports System
Imports System.IO

Namespace ConsoleApplication1
    Friend Class Program
        Private Shared Sub Main(args As String())
            Program.CopyMyFiles()
            Console.WriteLine("DONE!")
            Console.ReadLine()
        End Sub

        Private Shared Sub CopyMyFiles()
            Dim input_filepath As String = "Test.txt"
            Dim output_filepath As String = "Test_New.txt"
            Dim input As FileStream = New FileStream(input_filepath, FileMode.Open, FileAccess.ReadWrite)
            Dim output As FileStream = New FileStream(output_filepath, FileMode.Create, FileAccess.ReadWrite)
            Program.CopyStream(input, output)
        End Sub

        Public Shared Sub CopyStream(inputStream As Stream, outputStream As Stream)
            Dim buffer As Byte() = New Byte(1025)
            Dim bytesRead As Integer
            bytesRead = inputStream.Read(buffer, 0, buffer.Length)
            While bytesRead > 0
                outputStream.Write(buffer, 0, bytesRead)
                bytesRead = inputStream.Read(buffer, 0, buffer.Length)
            End While
            outputStream.Flush()
            inputStream.Close()
            outputStream.Close()
        End Sub
    End Class
End Namespace
person Daniel A.A. Pelsmaeker    schedule 22.03.2013
comment
Большое спасибо за вашу помощь и ваше объяснение, но я выполнил ваши шаги, и я все еще получаю нулевой файл, я обновил свой вопрос, еще раз спасибо - person ElektroStudios; 22.03.2013
comment
Да, он компилируется без каких-либо ошибок/исключений и создает файл с нулевым байтом, я попытался сейчас, добавив скобки, которые вы сказали в то время, но ничего не изменилось, мой код такой же, как и выше, только с этими скобками. - person ElektroStudios; 22.03.2013
comment
@ElektroHacker Ранее у вас был код, который закрывал поток вывода, но в вашем последнем коде этого больше нет. Вы должны закрыть выходной поток, это запишет буферизованные данные в поток. - person Daniel A.A. Pelsmaeker; 23.03.2013
comment
Я снова обновил свой вопрос, ваше терпение и ваша помощь приветствуются, но, к сожалению, я внес изменения, которые вы мне показали, и я продолжаю получать файл размером 0 байт (PS: входной файл весит 34 байта, имеет 15 строк текста ), тот же код работает на C#? - person ElektroStudios; 23.03.2013
comment
@ElektroHacker Я использовал какой-то инструмент для преобразования вашего кода в C#. Я проверил его, и он работает правильно на моем компьютере. Я преобразовал код обратно в VB.Net, поэтому взгляните на приведенный выше код. Сравните это со своим кодом, и, возможно, вы сможете найти какое-то тонкое различие, которое вызывает все это. Например, в моем коде есть As Byte() и As FileStream в тех местах, где их нет в вашем коде. Я не знаю, имеет ли это значение. - person Daniel A.A. Pelsmaeker; 23.03.2013
comment
Ни в коем случае, я протестировал этот преобразованный код, но я все еще получаю 0-байтовый файл, не могли бы вы опубликовать рабочую версию C #? - person ElektroStudios; 23.03.2013
comment
@ElektroHacker Я добавил код C# и некоторые вещи, на которые вам следует обратить внимание. - person Daniel A.A. Pelsmaeker; 23.03.2013
comment
Я не могу в это поверить, все вещи кажутся одинаковыми в вашей версии C # и в моей версии VB, но работает только C # vrs, единственная разница, которую я могу найти, заключается в том, что C # vrs - это приложение CLI, а VB vrs - это WinForm, хорошо, я принимаю ваш ответ, потому что вы дали мне рабочий код, который мне понадобится, теперь мне нужно найти переведенную ошибку с C # на VB.NET. спасибо за все еще раз! - person ElektroStudios; 23.03.2013
comment
Кто-то говорит мне, что проблема в VB.NET. Я не могу присвоить значение переменной в условии while, как в C#, вот и все! решено. - person ElektroStudios; 24.03.2013
comment
@ElektroHacker Если хотите, вы можете обновить свой пост с окончательным рабочим кодом. Другие пользователи с этой проблемой будут благодарны. - person Daniel A.A. Pelsmaeker; 24.03.2013