I am getting the result StreamReader
object.
I want to convert the result into byte[]
.
How can I convert StreamReader
to byte[]
?
Thanks
I am getting the result StreamReader
object.
I want to convert the result into byte[]
.
How can I convert StreamReader
to byte[]
?
Thanks
A StreamReader is for text, not plain bytes. Don't use a StreamReader, and instead read directly from the underlying stream.
Just throw everything you read into a MemoryStream
and get the byte array in the end. As noted, you should be reading from the underlying stream to get the raw bytes.
var bytes = default(byte[]);
using (var memstream = new MemoryStream())
{
var buffer = new byte[512];
var bytesRead = default(int);
while ((bytesRead = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
memstream.Write(buffer, 0, bytesRead);
bytes = memstream.ToArray();
}
Or if you don't want to manage the buffers:
var bytes = default(byte[]);
using (var memstream = new MemoryStream())
{
reader.BaseStream.CopyTo(memstream);
bytes = memstream.ToArray();
}
default()
? I don't think it makes things any more readable. –
Calumny MemoryStream
will manage the size for us as we read in the data. –
Incline MemoryStream
for this when a simple List<byte>
in conjunction with AddRange
would suffice. It won't change the code much, but it just feels weird to me to use a memory stream here :-) –
Interlard var
keyword whenever I can (for most local variables). I don't expect everyone to be comfortable with it but I'm ok with that. –
Incline MemoryStream
is just a wrapper to a byte[]
. A List<T>
is just a wrapper to a T[]
. It is much more appropriate to me, especially since we're already dealing with streams. –
Incline MemoryStream
is likely to be slightly more efficient as it's designed to efficiently handle arrays of bytes. For instance, you can add only a part of an array with Write
(unlike with AddRange
on a List<T>
), and it doesn't access byte arrays via an interface, which might be slightly less efficient. You can also get the underlying array directly with GetBuffer()
without creating a copy of it. Of course, this is only important if you have a big amount of data. –
Calumny var
...default
thing. It's making the code less readable and longer. Where exactly did you pick this up...? –
Calumny GetBuffer()
will return the underlying byte array only if it was passed in to the constructor (the array the MemoryStream
is wrapping). Otherwise, you'd have to use ToArray()
. As for the var
stuff, a lot of the code I deal with (particularly in other languages) use implicit typing and it's just a preference of mine to use it for local variables with exceptions for delegates/lambdas. It's kinda hard to explain so I'll just leave it at that. :) –
Incline GetBuffer()
would have thrown in this case. It appears it only does only in some select cases. –
Incline await reader.BaseStream.CopyToAsync(…)
instead of reader.BaseStream.CopyTo(…)
. –
Phonetics A StreamReader is for text, not plain bytes. Don't use a StreamReader, and instead read directly from the underlying stream.
StreamReader
reads a Stream
. It doesn't matter if you are streaming text or bytes, it can still read it. If you use StreamReader
and its methods (i.e. ReadLine()
or ReadToEnd()
) you ARE reading the underlying data of the stream. –
Stolon You can also use CopyTo:
var ms = new MemoryStream();
yourStreamReader.BaseStream.CopyTo(ms); // blocking call till the end of the stream
ms.GetBuffer().CopyTo(yourArray, ms.Length);
or
var ms = new MemoryStream();
var ct = yourStreamReader.BaseStream.CopyToAsync(ms);
await ct;
ms.GetBuffer().CopyTo(yourArray, ms.Length);
As Matti Virkkunen pointed out, you don't neccessarily need the MemoryStream. When the stream is not too long you can write into an array directly. Less allocated memory is the advantage.
using (var stream = File.OpenRead("your_file.ext"))
{
var length = stream.Length;
if (length <= int.MaxValue)
{
var result = new byte[length];
var bytesRead = stream.Read(result, 0, (int)length);
if (bytesRead == length) return result;
}
//fallback
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
BlobClient blob = container.GetBlobClient(path);
//blob.DownloadTo(@"temp\"+ file);
var response = blob.DownloadContent();
var stream = response.Value.Content.ToStream();
using (var sr = new StreamReader(stream))
{
using (MemoryStream ms = new MemoryStream())
{
sr.BaseStream.CopyTo(ms);
return Convert.ToBase64String(ms.ToArray()) ;
}
}
Since a few years have gone by, I think this implementation is better and simpler
using(var ms = new MemoryStream())
{
await yourStreamReader.BaseStream.CopyToAsync(ms);
//now you can do whatever you want with ms like returning it as a Base64 string
return Convert.ToBase64String(ms.ToArray());
}
For everyone saying to get the bytes, copy it to MemoryStream
, etc. - if the content isn't expected to be larger than computer's memory should be reasonably be expected to allow, why not just use StreamReader
's built in ReadLine()
or ReadToEnd()
? I saw these weren't even mentioned, and they do everything for you.
I had a use-case where I just wanted to store the path of a SQLite file from a FileDialogResult
that the user picks during the synching/initialization process. My program then later needs to use this path when it is run for normal application processes. Maybe not the ideal way to capture/re-use the information, but it's not much different than writing to/reading from an .ini file - I just didn't want to set one up for one value. So I just read it from a flat, one-line text file. Here's what I did:
string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!filePath.EndsWith(@"\")) temppath += @"\"; // ensures we have a slash on the end
filePath = filePath.Replace(@"\\", @"\"); // Visual Studio escapes slashes by putting double-slashes in their results - this ensures we don't have double-slashes
filePath += "SQLite.txt";
string path = String.Empty;
FileStream fs = new FileStream(filePath, FileMode.Open);
StreamReader sr = new StreamReader(fs);
path = sr.ReadLine(); // can also use sr.ReadToEnd();
sr.Close();
fs.Close();
fs.Flush();
return path;
If you REALLY need a byte[]
instead of a string
for some reason, using my example, you can always do:
byte[] toBytes;
FileStream fs = new FileStream(filePath, FileMode.Open);
StreamReader sr = new StreamReader(fs);
toBytes = Encoding.ASCII.GetBytes(path);
sr.Close();
fs.Close();
fs.Flush();
return toBytes;
(Returning toBytes
instead of path
.)
If you don't want ASCII
you can easily replace that with UTF8
, Unicode
, etc.
path
, a string variable (because why would you ever need bytes when you want to read text from a file?!). But I also included how to convert that string to bytes, if bytes were truly needed. –
Stolon Encoding.ASCII.GetBytes(...)
, but a quick look at the documentation for that shows it mentioning 7-bit, so the input may well get mangled. Similarly, UTF-8 encoding makes assumptions about the input that also don't hold when fed with arbitrary binary files. –
Reyreyes Encoding.ASCII.GetBytes()
, but Encoding.UTF8.GetBytes()
, Encoding.Unicode.GetBytes()
, etc. Use the intellisense before just ragging on an answer. –
Stolon UTF-8
, whereas I have it using ASCII
& that was only if they REALLY found my 2nd method necessary, because the main idea in my post was to avoid the encodings altogether by doing StreamReader
and a sr.ReadLine
to string. Plus, your link only talks about it losing bytes after doing a round-trip if you do a GetString
then a GetBytes
. I'm not doing that at all - it does the GetBytes
from the StreamReader
, which is EXACTLY HOW you are SUPPOSED to do it & lets it be stored as bytes
, afterwards. You can stream bytes all day. –
Stolon © 2022 - 2024 — McMap. All rights reserved.
StreamReader
reads aStream
. It doesn't matter if you are streaming text or bytes, it can still read it. If you useStreamReader
and its methods (i.e.ReadLine()
orReadToEnd()
) you ARE reading the underlying data of the stream. – Stolon