Как скопировать содержимое одного потока в другой?

  1. DFS легче реализовать
  2. . Когда DFS найдет цикл, стек будет содержать узлы, образующие цикл. То же самое не относится к BFS, поэтому вам нужно сделать дополнительную работу, если вы хотите также распечатать найденный цикл. Это делает DFS намного более удобным.
501
задан David Heffernan 26 September 2014 в 17:12
поделиться

8 ответов

От.NET 4.5 на, существует Stream.CopyToAsync метод

input.CopyToAsync(output);

, Это возвратится Task , который может быть продолжен, когда завершено, как так:

await input.CopyToAsync(output)

// Code from here on will be run in a continuation.

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

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

Кроме того, этот вызов (и это - подлежащая изменению деталь реализации) все еще упорядочивает чтения и записи (он просто не тратит впустую потоки, блокирующиеся на завершении ввода-вывода).

От.NET 4.0 на, существует, Stream.CopyTo метод

input.CopyTo(output);

Для.NET 3.5 и прежде

нет ничего испеченного в платформу для помощи с этим; необходимо скопировать содержание вручную, как так:

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write (buffer, 0, read);
    }
}

Примечание 1: Этот метод позволит Вам сообщать относительно прогресса (x чтение байтов до сих пор...)
Примечание 2: Почему использование фиксированный размер буфера а не input.Length? Поскольку та Длина не может быть доступной! От эти документы :

, Если класс, полученный из Потока, не поддерживает поиск, вызовы к Длине, SetLength, Положение, и Искать бросает NotSupportedException.

675
ответ дан 9 revs, 8 users 28% 26 September 2014 в 17:12
поделиться

Основные вопросы, которые дифференцируют реализации "CopyStream":

  • размер буфера чтения
  • размер записей
  • Может мы использовать больше чем один поток (пишущий, в то время как мы читаем).

ответы на эти вопросы приводят к весьма различным реализациям CopyStream и зависят от того, какие потоки Вы имеете и что Вы пытаетесь оптимизировать. "Лучшая" реализация должна была бы даже знать, какие определенные аппаратные средства потоки читали и писали в.

1
ответ дан fryguybob 26 September 2014 в 17:12
поделиться

К сожалению, нет никакого действительно простого решения. Можно попробовать что-то как этот:

Stream s1, s2;
byte[] buffer = new byte[4096];
int bytesRead = 0;
while (bytesRead = s1.Read(buffer, 0, buffer.Length) > 0) s2.Write(buffer, 0, bytesRead);
s1.Close(); s2.Close();

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

Всегда проверяют документацию определенного потокового класса, который Вы используете перед использованием универсального решения.

0
ответ дан Tamas Czinege 26 September 2014 в 17:12
поделиться

Может быть способ сделать это более эффективно, в зависимости от того, с каким потоком Вы работаете. Если можно преобразовать один или оба из потоков к MemoryStream, можно использовать метод GetBuffer для работы непосредственно с массивом байтов, представляющим данные. Это позволяет Вам использовать методы как Массив. CopyTo, какой краткий обзор далеко все проблемы повышен fryguybob. Можно просто доверять.NET для знания оптимального способа скопировать данные.

0
ответ дан Coderer 26 September 2014 в 17:12
поделиться

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

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[32768];
    long TempPos = input.Position;
    while (true)    
    {
        int read = input.Read (buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write (buffer, 0, read);
    }
    input.Position = TempPos;// or you make Position = 0 to set it at the start
}

, но если это находится во времени выполнения не использование процедуры Вы, shpuld используют поток памяти

Stream output = new MemoryStream();
byte[] buffer = new byte[32768]; // or you specify the size you want of your buffer
long TempPos = input.Position;
while (true)    
{
    int read = input.Read (buffer, 0, buffer.Length);
    if (read <= 0)
        return;
    output.Write (buffer, 0, read);
 }
    input.Position = TempPos;// or you make Position = 0 to set it at the start
0
ответ дан Kronass 27 September 2014 в 04:12
поделиться

Я использую следующие методы расширения. Они оптимизировали перегрузки для случаев, когда одним потоком является MemoryStream.

    public static void CopyTo(this Stream src, Stream dest)
    {
        int size = (src.CanSeek) ? Math.Min((int)(src.Length - src.Position), 0x2000) : 0x2000;
        byte[] buffer = new byte[size];
        int n;
        do
        {
            n = src.Read(buffer, 0, buffer.Length);
            dest.Write(buffer, 0, n);
        } while (n != 0);           
    }

    public static void CopyTo(this MemoryStream src, Stream dest)
    {
        dest.Write(src.GetBuffer(), (int)src.Position, (int)(src.Length - src.Position));
    }

    public static void CopyTo(this Stream src, MemoryStream dest)
    {
        if (src.CanSeek)
        {
            int pos = (int)dest.Position;
            int length = (int)(src.Length - src.Position) + pos;
            dest.SetLength(length); 

            while(pos < length)                
                pos += src.Read(dest.GetBuffer(), pos, length - pos);
        }
        else
            src.CopyTo((Stream)dest);
    }
31
ответ дан 22 November 2019 в 22:33
поделиться

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

public static void CopyStream(Stream input, Stream output)
{
  using (StreamReader reader = new StreamReader(input))
  using (StreamWriter writer = new StreamWriter(output))
  {
    writer.Write(reader.ReadToEnd());
  }
}

ПРИМЕЧАНИЕ: Также могут возникнуть некоторые проблемы, связанные с двоичными данными и кодировками символов.

2
ответ дан 22 November 2019 в 22:33
поделиться

MemoryStream имеет .WriteTo (outstream);

, а .NET 4.0 имеет .CopyTo для обычного объекта потока.

.NET 4.0:

instream.CopyTo(outstream);
64
ответ дан 22 November 2019 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: