как буферизовать входной поток до его завершения - PullRequest
1 голос
/ 12 октября 2011

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

может кто-нибудь помочь?

мой код до сих пор:

    public String uploadUserImage(Stream stream)
    {
          Stream fs = stream;

          BinaryReader br = new BinaryReader(fs);

          Byte[] bytes = br.ReadBytes((Int32)fs.Length);// this causes exception

          File.WriteAllBytes(filepath, bytes);
    }

Ответы [ 4 ]

6 голосов
/ 12 октября 2011

Вместо того, чтобы пытаться получить длину, вы должны читать из потока, пока он не вернет, что он «готов».В .NET 4 это действительно просто:

// Assuming we *really* want to read it into memory first...
MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
memoryStream.Position = 0;
File.WriteAllBytes(filepath, memoryStream);

В .NET 3.5 нет метода CopyTo, но вы можете написать что-то похожее самостоятельно:

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

Однако сейчасу нас есть что скопировать поток, зачем сначала читать все это в памяти?Давайте просто напишем это прямо в файл:

using (FileStream output = File.OpenWrite(filepath))
{
    CopyStream(stream, output); // Or stream.CopyTo(output);
}
1 голос
/ 12 октября 2011

Я не уверен, что вы возвращаете (или не возвращаете), но что-то вроде этого может работать для вас:

public String uploadUserImage(Stream stream) {
  const int KB = 1024;
  Byte[] bytes = new Byte[KB];
  StringBuilder sb = new StringBuilder();
  using (BinaryReader br = new BinaryReader(stream)) {
    int len;
    do {
      len = br.Read(bytes, 0, KB);
      string readData = Encoding.UTF8.GetString(bytes);
      sb.Append(readData);
    } while (len == KB);
  }
  //File.WriteAllBytes(filepath, bytes);
  return sb.ToString();
}

Строка может вместить до 2 ГБ, я полагаю.

0 голосов
/ 06 октября 2018

Ответ Джона Скитса для .Net 3.5 и ниже с использованием чтения буфера на самом деле выполнен неправильно.

Буфер не очищается между чтениями, что может привести к проблемам при любом чтении, которое возвращает менее 8192, например, если при втором чтении читать 192 байта, последние 8000 байтов из первого чтения останутся в буфере, все еще будет в буфере который затем будет возвращен в поток.

Мой код ниже вы предоставляете ему Stream, и он вернет массив IEnumerable.
Используя это, вы можете записать его и записать в MemoryStream, а затем использовать .GetBuffer () для получения скомпилированного объединенного байта [].

private IEnumerable<byte[]> ReadFullStream(Stream stream) {
   while(true) {
        byte[] buffer = new byte[8192];//since this is created every loop, its buffer is cleared
        int bytesRead = stream.Read(buffer, 0, buffer.Length);//read up to 8192 bytes into buffer
        if (bytesRead == 0) {//if we read nothing, stream is finished
            break;
        }
        if(bytesRead < buffer.Length) {//if we read LESS than 8192 bytes, resize the buffer to essentially remove everything after what was read, otherwise you will have nullbytes/0x00bytes at the end of your buffer
            Array.Resize(ref buffer, bytesRead);
        }
        yield return buffer;//yield return the buffer data
    }//loop here until we reach a read == 0 (end of stream)
}
0 голосов
/ 12 октября 2011

Попробуйте это:

    using (StreamWriter sw = File.CreateText(filepath))
    {
        stream.CopyTo(sw);
        sw.Close();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...