我正在实施一个接受图像流的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);
}
答案 0 :(得分:6)
您应该从流中读取,直到它返回“已完成”,而不是尝试获取长度。在.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 :(得分:1)
我不确定你要回来的东西(或不回来),但是这样的东西可能适合你:
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 GB。
答案 2 :(得分:0)
试试这个:
using (StreamWriter sw = File.CreateText(filepath))
{
stream.CopyTo(sw);
sw.Close();
}
答案 3 :(得分:-1)
Jon Skeets使用缓冲区读取对.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)
}