How can I convert StreamWriter to a Stream? - c#

I am trying to create a file using FileHelpers and then write that file out using SshNet all in memory.
So far I have the following:
var engine = new FileHelperEngine<MyObject>();
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
engine.WriteStream(sw, MyData);
SshHelper ssh = new SshHelper("","","");
ssh.WriteFile("MyPath", sw.BaseStream);
However my issue is with the WriteFile method since it requires a Stream parameter and when I run my code I am getting an empty file.
How can I convert my StreamWriter (sw variable) into a Stream parameter?
EDIT:
I've tried both(not at the same time):
ms.Seek(0, SeekOrigin.Begin);
ms.Position = 0;
and it still writes a 0 byte file.
I further tested by using FileHelper to write to my local disk to verify that I have data. (Which I do)

your MemoryStream is the stream, the StreamWriter is just writing to it. Try passing ms in, instead of sw.

Before WriteFile try setting the Position of your Stream to 0: ms.Seek( 0, SeekOrigin.Begin )

Related

How to Convert from MemoryStream to FileStream to pass to MS Graph?

I have a MemoryStream object that contains the contents of a file. I would like to convert it from a MemoryStream to a FileStream in order to pass it to MS Graph's LargeFileUploadTask() method.
It seems that the method accepts the generic type called "Stream" so I tried using it as is, but it's taking a very long time. In fact I get an HTTP timeout for larger streams.
I have another method similar to this one that also uses the LargeFileUploadTask and trying to upload the same file works - it's using a FileStream (the difference between the two methods is that one writes to a local file, and then opens a filestream before sending to MS Graph, and the one here receives a memorystream as a parameter)
Code
private static async Task<Boolean> UploadInChunksToSharepoint(MemoryStream fileContents, string fileName)
....
// Max slice size must be a multiple of 320 KiB
int maxSliceSize = 320 * 204800 * 4;
var fileUploadTask =
new LargeFileUploadTask<DriveItem>(uploadSession, fileContents, maxSliceSize);
What I've Tried
In reading other posts, I see that there's a WriteTo method in the fileContents object. So i tried something like this:
FileStream fileStream = new FileStream();
fileContents.WriteTo(fileStream);
But ... I guess I can't do that because the FileStream doesn't allow you to just initialize without any parameters. If there's a way... I'd like to be able to try this to compare apples to apples between the two methods to see why there's such a time diff.
In the meantime, I'm poking around the rest of the code to see if there might be other deltas that I just missed.
The OP said the problem was that they forgot to rewind the MemoryStream before attempting to use it as the source of a HTTP request payload.
#Dai, that's all it was. I reset position to 0. if you want to add as answer... i'll accept
Gladly.
So watch out if you have this:
using( MemoryStream ms = new MemoryStream() )
{
using( StreamWriter wtr = new StreamWriter( ms, false ) )
{
CopyLoremIpsum( wtr );
}
await UploadStreamAsync( ms );
}
The StreamWriter (or any other writing action) will set the MemoryStream.Position to the end of the stream, where it cannot be read any further (basically as if you had a cassette tape movie or VHS played past the end-credits).
So make sure you reset .Position or use .Seek after writing to it, but before attempting to read from it:
using( MemoryStream ms = new MemoryStream() )
{
using( StreamWriter wtr = new StreamWriter( ms, false ) )
{
CopyLoremIpsum( wtr );
}
ms.Position = 0;
await UploadStreamAsync( ms );
}
I have a MemoryStream object that contains the contents of a file. I would like to convert it from a MemoryStream to a FileStream in order to pass it to MS Graph's LargeFileUploadTask() method
But the docs you linked simply state that a Stream is required:
Yes, a FileStream is a Stream but a MemoryStream is also a Stream and is a "readable, seekable stream" like the docs say is required; it means you can just pass the MemoryStream you have for the uploadStream parameter.
Perhaps make sure you've Seek'd it to Position 0 before you pass it.. If you've just finished writing into a Memorystream, it's Positioned at the end. If you then pass it to something that will start reading from it, that thing usually reads nothing (because the stream is at the end) - seek the stream back to the start/where you want the upload to begin because you should assume that the thing you give it to will not seek it before reading from it

Filestream.write does not work

I used the following code to write on *.txt file, but nothing happens. Even, there is no exception.
FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None); //Creating a stream with certain features to a file
StreamWriter writer = new StreamWriter(fs); //Use the fs to write
// writer.WriteLine(Text.Text); none of the following methods works
writer.Write("aaaaaaaaaaaa");
fs.Close();
Thanks
Try to enclose it in a using block like this:
using ( FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None))
using (StreamWriter fw = new StreamWriter(fs))
{
fw.Write("aaaaaaaaaaaa");
}
A StreamWriter buffers data before writing it to the underlying stream. You need to flushes the buffer by disposing the StreamWriter

Inconsistent file size change while writing bytes from stream to a file

I have a file with size 10124, I am adding a byte array, which has length 4 in the beginning of the file.
After that the file size should become 10128, but as I write it to file, the size decreased to 22 bytes. I don't know where is the problem
public void AppendAllBytes(string path, byte[] bytes)
{
var encryptedFile = new FileStream(path, FileMode.Open, FileAccess.Read);
////argument-checking here.
Stream header = new MemoryStream(bytes);
var result = new MemoryStream();
header.CopyTo(result);
encryptedFile.CopyTo(result);
using (var writer = new StreamWriter(#"C:\\Users\\life.monkey\\Desktop\\B\\New folder (2)\\aaaaaaaaaaaaaaaaaaaaaaaaaaa.docx.aef"))
{
writer.Write(result);
}
}
How can I write bytes to the file?
The issue seems to be caused by:
using a StreamWriter to write binary formatted data. The name does not inthuitively suggest this, but the StreamWriter class is suited for writing textual data.
passing an entire stream instead of the actual binary data. To obtain the bytes stored in a MemoryStream, use its convenient ToArray() method.
I suggest you the following code:
public void AppendAllBytes(string path, byte[] bytes)
{
var fileName = #"C:\\Users\\life.monkey\\Desktop\\B\\New folder (2)\\aaaaaaaaaaaaaaaaaaaaaaaaaaa.docx.aef";
using (var encryptedFile = new FileStream(path, FileMode.Open, FileAccess.Read))
using (var writer = new BinaryWriter(File.Open(fileName, FileMode.Append)))
using (var result = new MemoryStream())
{
encryptedFile.CopyTo(result);
result.Flush(); // ensure header is entirely written.
// write header directly, no need to put it in a memory stream
writer.Write(bytes);
writer.Flush(); // ensure the header is written to the result stream.
writer.Write(result.ToArray());
writer.Flush(); // ensure the encryptdFile is written to the result stream.
}
}
The code above uses the BinaryWriter class which is better suited for binary data. It has a Write(byte[] bytes) method overload that is used above to write an entire array to the file. The code uses regular calls to the Flush() method that some may consider not needed, but these guarantee in general, that all the data written prior the call of the Flush() method is persisted within the stream.

Convert string to filestream in c#

Just started with writing unit tests and I am now, blocked with this situation:
I have a method which has a FileStream object and I am trying to pass a "string" to it.
So, I would like to convert my string to FileStream and I am doing this:
File.WriteAllText(string.Concat(Environment.ExpandEnvironmentVariables("%temp%"),
#"/test.txt"), testFileContent); //writes my string to a temp file!
new FileStream(string.Concat(Environment.ExpandEnvironmentVariables("%temp%"),
#"/test.txt"), FileMode.Open) //open that temp file and uses it as a fileStream!
close the file then!
But, I guess there must be some very simple alternative to convert a string to a fileStream.
Suggestions are welcome! [Note there are other answers to this question in stackoverflow but none seems to be a straight forward solution to that]
Thanks in advance!
First of all change your method to allow Stream instead of FileStream. FileStream is an implementation which, as I remember, does not add any methods or properties, just implement abstract class Stream. And then using below code you can convert string to Stream:
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
As FileStream class provides a stream for a file and hence it's constructor requires the path of the file,mode, permission parameter etc. to read the file into stream and hence it is used to read the text from file into stream. If we need to convert string to stream first we need to convert string to bytes array as stream is a sequence of bytes. Below is the code.
//Stream is a base class it holds the reference of MemoryStream
Stream stream = new MemoryStream();
String strText = "This is a String that needs to beconvert in stream";
byte[] byteArray = Encoding.UTF8.GetBytes(strText);
stream.Write(byteArray, 0, byteArray.Length);
//set the position at the beginning.
stream.Position = 0;
using (StreamReader sr = new StreamReader(stream))
{
string strData;
while ((strData= sr.ReadLine()) != null)
{
Console.WriteLine(strData);
}
}

Writing to stream without file path

I have legacy class that writes some results to a file using StreamWriter, created with constructor that accepts FileStream, which is previously created by giving it's constructor a file path:
using (FileStream fs = File.Open(outputFilePath, FileMode.Create))
using (StreamWriter sw = new StreamWriter(fs))
{
MyFileWriter.WriteToFile(someData, sw);
}
By the way, stated code is used in WCF service.
Now, I have new requirement where I have to save file to a client file system and I have constraint that I can only send byte[] to client. I would like to make minimal changes to existing code to support this, so is there, for example, some kind of stream which I can create wihtout the need to specify the file path in it's constructor? Later I would convert this stream to byte[].
I'm open to any other idea you might have, as well.
You can use MemoryStream,
byte[] result;
using (MemoryStream ms = new MemoryStream())
using (StreamWriter sw = new StreamWriter(ms))
{
MyFileWriter.WriteToFile(someData, sw);
result = ms.ToArray();
}
// use the result byte[]
Use MemoryStream.
using (MemoryStream ms = new MemoryStream())
{
using (StreamWriter sw = new StreamWriter(ms))
{
MyFileWriter.WriteToFile(someData, sw);
}
}

Categories

Resources