Convert StreamReader to byte[]

2019-03-22 12:38发布

问题:

I am getting the result streamreader object.

I want to convert the result into byte[].

How can i convert streamreader to byte[]?

Thanks

回答1:

A StreamReader is for text, not plain bytes. Don't use a StreamReader, and instead read directly from the underlying stream.



回答2:

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();
}


回答3:

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);


回答4:

You can use this code: You shouldn't use this code:

byte[] bytes = streamReader.CurrentEncoding.GetBytes(streamReader.ReadToEnd());

Please see the comment to this answer as to why. I will leave the answer, so people know about the problems with this approach, because I didn't up till now.



回答5:

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.



标签: c# stream