J'ai la méthode constructeur suivante qui ouvre un MemoryStream
à partir d'un chemin de fichier:
MemoryStream _ms;
public MyClass(string filePath)
{
byte[] docBytes = File.ReadAllBytes(filePath);
_ms = new MemoryStream();
_ms.Write(docBytes, 0, docBytes.Length);
}
Je dois changer cela pour accepter un Stream
au lieu d'un chemin de fichier. Quel est le moyen le plus simple/le plus efficace pour obtenir un MemoryStream
à partir de l'objet Stream
?
Si vous modifiez votre classe pour accepter un Stream au lieu d'un nom de fichier, ne vous embêtez pas à convertir en MemoryStream. Laissez le flux sous-jacent gérer les opérations:
public class MyClass
{
Stream _s;
public MyClass(Stream s) { _s = s; }
}
Mais si vous avez vraiment besoin d'un MemoryStream pour les opérations internes, vous devrez copier les données du Stream source dans le MemoryStream:
public MyClass(Stream stream)
{
_ms = new MemoryStream();
CopyStream(stream, _ms);
}
// Merged From linked CopyStream below and Jon Skeet's ReadFully example
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[16*1024];
int read;
while((read = input.Read (buffer, 0, buffer.Length)) > 0)
{
output.Write (buffer, 0, read);
}
}
Dans .NET 4, vous pouvez utiliser Stream.CopyTo pour copier un flux, au lieu des méthodes de brassage maison répertoriées dans les autres réponses.
MemoryStream _ms;
public MyClass(Stream sourceStream)
_ms = new MemoryStream();
sourceStream.CopyTo(_ms);
}
Utilisez ceci:
var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
Cela convertira Stream
en MemoryStream
.
Vous devrez lire toutes les données de l'objet Stream dans un byte[]
buffer puis passez-le dans MemoryStream
via son constructeur. Il peut être préférable d'être plus précis sur le type d'objet de flux que vous utilisez. Stream
est très générique et peut ne pas implémenter l'attribut Length
, ce qui est plutôt utile lors de la lecture de données.
Voici du code pour vous:
public MyClass(Stream inputStream) {
byte[] inputBuffer = new byte[inputStream.Length];
inputStream.Read(inputBuffer, 0, inputBuffer.Length);
_ms = new MemoryStream(inputBuffer);
}
Si l'objet Stream
n'implémente pas l'attribut Length
, vous devrez implémenter quelque chose comme ceci:
public MyClass(Stream inputStream) {
MemoryStream outputStream = new MemoryStream();
byte[] inputBuffer = new byte[65535];
int readAmount;
while((readAmount = inputStream.Read(inputBuffer, 0, inputBuffer.Length)) > 0)
outputStream.Write(inputBuffer, 0, readAmount);
_ms = outputStream;
}
J'utilise cette combinaison de méthodes d'extension:
public static Stream Copy(this Stream source)
{
if (source == null)
return null;
long originalPosition = -1;
if (source.CanSeek)
originalPosition = source.Position;
MemoryStream ms = new MemoryStream();
try
{
Copy(source, ms);
if (originalPosition > -1)
ms.Seek(originalPosition, SeekOrigin.Begin);
else
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
catch
{
ms.Dispose();
throw;
}
}
public static void Copy(this Stream source, Stream target)
{
if (source == null)
throw new ArgumentNullException("source");
if (target == null)
throw new ArgumentNullException("target");
long originalSourcePosition = -1;
int count = 0;
byte[] buffer = new byte[0x1000];
if (source.CanSeek)
{
originalSourcePosition = source.Position;
source.Seek(0, SeekOrigin.Begin);
}
while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
target.Write(buffer, 0, count);
if (originalSourcePosition > -1)
{
source.Seek(originalSourcePosition, SeekOrigin.Begin);
}
}
Comment copier le contenu d'un flux dans un autre?
regarde ça. accepter un flux et copier dans la mémoire. vous ne devez pas utiliser .Length
pour juste Stream
car il n'est pas nécessairement implémenté dans chaque Stream concret.
public static void Do(Stream in)
{
_ms = new MemoryStream();
byte[] buffer = new byte[65536];
while ((int read = input.Read(buffer, 0, buffer.Length))>=0)
_ms.Write (buffer, 0, read);
}
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
Vous pouvez simplement faire:
var ms = new MemoryStream(File.ReadAllBytes(filePath));
La position du flux est 0 et prête à l'emploi.