Changing from MemoryStream to Stream in C# - c#

Below is the code where I am passing memory stream and reading it and doing the necessary operation afterwards. Now the requirement has changed and instead of Memory stream, I will be passing Stream and that starts giving me error. I would like to know how can I handle the below method if contents returned here is of Stream type. Now it works fine when my contents is of type MemoryStream.
public async Task<string> ReadStream(string containerName, string digestFileName, string fileName, string connectionString)
{
string data = string.Empty;
string fileExtension = Path.GetExtension(fileName);
var contents = await DownloadBlob(containerName, digestFileName, connectionString);
if (fileExtension == ".gz")
{
using (var unzipper = new GZipStream(contents, CompressionMode.Decompress))
{
using (StreamReader reader = new StreamReader(unzipper, Encoding.UTF8))
{
data = reader.ReadToEnd();
}
}
}
else
{
data = Encoding.UTF8.GetString(contents.ToArray());
}
return data;
}

I'm going to assume the issue is contents.ToArray(), since Stream desn't have a ToArray() method.
In this case, you'll be better off using a StreamReader:
using (var reader = new StreamReader(contents))
{
data = reader.ReadToEnd();
}
StreamReader uses Encoding.UTF8 by default, but you can specify it explicitly if you want: new StreamReader(contents, Encoding.UTF8).
You'll note that you're already doing this a few lines above, to read from the unzipper stream.

Related

Saving a Xamarin image to file

Hi so I'm trying to save an image selected by the user to file so that i can later upload it to my mySQL database.
So I have this code:
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Please pick a selfie"
});
var stream = await result.OpenReadAsync();
resultImage.Source = ImageSource.FromStream(() => stream);
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string filename = Path.Combine(path, "myfile");
using (var streamWriter = new StreamWriter(filename, true))
{
streamWriter.WriteLine(GetImageBytes(stream).ToString());
}
using (var streamReader = new StreamReader(filename))
{
string content = streamReader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(content);
}
Here's the GetImageBytes(..) function:
private byte[] GetImageBytes(Stream stream)
{
byte[] ImageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
ImageBytes = memoryStream.ToArray();
}
return ImageBytes;
}
The code kind of works, it creates a file but doesn't save the image. Instead it saves "System.Bytes[]". It saves the name of the object, not the contents of the object.
myfile
enter image description here
Any help would be really appreciated. Thanks!
StreamWriter is for writing formatted strings, not binary data. Try this instead
File.WriteAllBytes(filename,GetImageBytes(stream));
Encode the byte array as a base64 string, then store that in the file:
private string GetImageBytesAsBase64String(Stream stream)
{
var imageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
imageBytes = memoryStream.ToArray();
}
return Convert.ToBase64String(imageBytes);
}
If you later need to retrieve the image bytes from the file, you can use the corresponding Convert.FromBase64String(imageBytesAsBase64String) method.

StreamReader save ReadLine to string and use it in if

Hi I want to save the output from reader.ReadToEnd() to a string and check if the string is "Access" but I don't know how to do it.
string url = "https://mywebsite.com/check.php";
Stream mystream = client.OpenRead(url);
StreamReader reader = new StreamReader(mystream);
Console.WriteLine(reader.ReadToEnd()); //The text will be "Access"
//Pseudecode start
string line = reader.ReadToEnd();
if (line == "Access")
{
useraccess = true;
Console.WriteLine("Done!");
}
mystream.Close();
You are reading the stream twice without any sort of reset, it would be more advisable to read it only once. Also you should be disposing of your stream and streamreader appropriately. See the following:
string url = "https://mywebsite.com/check.php";
string remoteData = null;
using (Stream mystream = client.OpenRead(url))
using (StreamReader reader = new StreamReader(mystream))
remoteData = reader.ReadToEnd();
Console.WriteLine(remoteData); //The text will be "Access"
//Pseudecode start
if (remoteData == "Access")
{
useraccess = true;
Console.WriteLine("Done!");
}
This should work under the assumption that ReadToEnd() is returning what you wanted it to return. I don't know what your endpoint looks like so I can't verify.

Base64 to StreamContent to upload image without pulling from file system

I'd like to be able to change this code so that I don't have to pull from a file on a file system, but rather use a base64 value that is saved in a database. Does anyone here know enough about StreamContent to know what I need to do to accomplish this?
The file is a jpeg file.
private static StreamContent FileMultiPartBody(string fullFilePath)
{
var fileInfo = new FileInfo(fullFilePath);
var fileContent = new StreamContent(fileInfo.OpenRead());
// Manually wrap the string values in escaped quotes.
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = string.Format("\"{0}\"", fileInfo.Name),
Name = "\"signature\"",
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return fileContent;
}
StreamContent is just a wrapper of another stream (the stream returned from fileInfo.OpenRead() in your example). All you need to do is replace that stream with a stream from your database and return that. You can also replace the fileInfo.Name with a Path.GetFileName(fullFilePath) call.
private Stream GetStreamFromDatabase(string fullFilePath)
{
//TODO
}
private static StreamContent FileMultiPartBody(string fullFilePath)
{
var fileContent = new StreamContent(GetStreamFromDatabase(fullFilePath))
// Manually wrap the string values in escaped quotes.
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
FileName = string.Format("\"{0}\"", Path.GetFileName(fullFilePath)),
Name = "\"signature\"",
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return fileContent;
}
If you need help converting a base64 value from a database to a stream I would suggest asking a separate question about that.

Read the content of an xml file within a zip package

I am required to read the contents of an .xml file using the Stream (Here the xml file is existing with in the zip package). Here in the below code, I need to get the file path at runtime (here I have hardcoded the path for reference). Please let me know how to read the file path at run time.
I have tried to use string s =entry.FullName.ToString(); but get the error "Could not find the Path". I have also tried to hard code the path as shown below. however get the same FileNotFound error.
string metaDataContents;
using (var zipStream = new FileStream(#"C:\OB10LinuxShare\TEST1\Temp" + "\\"+zipFileName+".zip", FileMode.Open))
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
if (entry.Name.EndsWith(".xml"))
{
FileInfo metadataFileInfo = new FileInfo(entry.Name);
string metadataFileName = metadataFileInfo.Name.Replace(metadataFileInfo.Extension, String.Empty);
if (String.Compare(zipFileName, metadataFileName, true) == 0)
{
using (var stream = entry.Open())
using (var reader = new StreamReader(stream))
{
metaDataContents = reader.ReadToEnd();
clientProcessLogWriter.WriteToLog(LogWriter.LogLevel.DEBUG, "metaDataContents : " + metaDataContents);
}
}
}
}
}
I have also tried to get the contents of the .xml file using the Stream object as shown below. But here I get the error "Stream was not readable".
Stream metaDataStream = null;
string metaDataContent = string.Empty;
using (Stream stream = entry.Open())
{
metaDataStream = stream;
}
using (var reader = new StreamReader(metaDataStream))
{
metaDataContent = reader.ReadToEnd();
}
Kindly suggest, how to read the contents of the xml with in a zip file using Stream and StreamReader by specifying the file path at run time
Your section code snippet is failing because when you reach the end of the first using statement:
using (Stream stream = entry.Open())
{
metaDataStream = stream;
}
... the stream will be disposed. That's the point of a using statment. You should be fine with this sort of code, but load the XML file while the stream is open:
XDocument doc;
using (Stream stream = entry.Open())
{
doc = XDocument.Load(stream);
}
That's to load it as XML... if you really just want the text, you could use:
string text;
using (Stream stream = entry.Open())
{
using (StreamReader reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
}
Again, note how this is reading before it hits the end of either using statement.
Here is a sample of how to read a zip file using .net 4.5
private void readZipFile(String filePath)
{
String fileContents = "";
try
{
if (System.IO.File.Exists(filePath))
{
System.IO.Compression.ZipArchive apcZipFile = System.IO.Compression.ZipFile.Open(filePath, System.IO.Compression.ZipArchiveMode.Read);
foreach (System.IO.Compression.ZipArchiveEntry entry in apcZipFile.Entries)
{
if (entry.Name.ToUpper().EndsWith(".XML"))
{
System.IO.Compression.ZipArchiveEntry zipEntry = apcZipFile.GetEntry(entry.Name);
using (System.IO.StreamReader sr = new System.IO.StreamReader(zipEntry.Open()))
{
//read the contents into a string
fileContents = sr.ReadToEnd();
}
}
}
}
}
catch (Exception)
{
throw;
}
}

asp.net mvc generate data to download file

public ActionResult GetFile(string dateStr, string serverName, string foodName)
{
using (var memoStream = new MemoryStream(1024 * 5))
{
using (StreamWriter writer = new StreamWriter(memoStream))
{
var dataFilter = new CapacityDataFilter(dateStr, serverName, feedName);
dataFilter.FilterDataByServerAndFeed();
writer.WriteLine("Feed, StreamMin, TotalMsgNumber, TotalMsgSize, PeakRateMsgNumber, PeakRateMsgSize");
foreach (var element in dataFilter.DataInTheDay)
{
writer.WriteLine(string.Format("{0},{1},{2},{3},{4},{5}",
element.Feed, element.StreamMin,
element.TotalMsgNumber, element.TotalMsgSize,
element.PeakRateMsgNumber, element.PeakRateMsgSize));
}
return File(memoStream, "text/csv", fileName);
}
}
}
Exception Details: System.ObjectDisposedException: Cannot access a closed Stream.
this action doesn't work, how to make a download action?
"this action not work" is wrong way to explain problems...
But in this case you are lucky: you are trying to send incomplete data in memory stream that is seeked to the end, and as second issue stream will be disposed by the time File action actually executes.
The best fix is to move code outisde inner using and return new MemoryStream on buffer of old stream:
using (var memoStream = new MemoryStream(1024 * 5))
{
using (StreamWriter writer = new StreamWriter(memoStream))
{
...
}
return File(
new MemoryStream(memoStream.GetBuffer(), memoStream.length),
"text/csv", fileName);
}
Flush + Seek as proposed by armen.shimoon would work too in other cases when you are using stream immediately:
writer.Flush();
memoStream.Flush();
memoStream.Position = 0;
// do something with MemoryStream right here before either of `using`ends.

Categories