none
It is possible to wrap StreamWriter in FileStream

    Question

  • Hello,

    Trying to understand a project that I have to refactor, I found these methods in a kind of repository classes

            public static void CreateAllText(string path, string contenidos, Encoding encoding)
            {
                if (!File.Exists(path))
                {
                    using (FileStream FileText = new FileStream(path, FileMode.Create, FileAccess.Write))
                    {
                        using (StreamWriter sDocwriter = new StreamWriter(FileText, encoding, 1024, false))    
                        {
                            sDocwriter.Write(contenidos);
                        }
                    }
                }
                else
                {
                    throw new ArgumentNullException("Error: file Exists overwrite");
                }
            }
    
            public static void AppendText(string path, string contenidos, Encoding encoding)
            {
                if (File.Exists(path))
                {
                    using (FileStream FileText = new FileStream(path, FileMode.Append, FileAccess.ReadWrite))
                    {
                        using (StreamWriter sDocwriter = new StreamWriter(FileText, encoding, 1024, false))      
                        {
                            sDocwriter.Write(contenidos);
                        }
                    }
                }
                else
                {
                    throw new ArgumentNullException("Error: Not File exists");
                }
            }

    first one write all document, but creates a FileStream and then a StreamWriter

    the other is to append FileStream but Writing in a StreamWriter??? I need a explanation!!

    Thursday, December 6, 2018 10:14 PM

All replies

  • Andrew B. Painter

    The concept of any "stream" in programming is a steady flow of contiguous data that is not relevant to the IO device, but is relevant to an end user or consuming algorithms.  So there's System.IO.Stream which implements the features and functions common to everything else in System.IO that has the word "stream" in its name, and they're all more or less the same thing.

    So the System.IO.StreamWriter writes to a stream.  The System.IO.StreamReader reads from a stream.  The System.IO.FileStream wrappers around a filesystem IO and includes the functions of both a StreamReader and a StreamWriter.  So where you see new StreamWriter(FileText) you're seeing a new instance of the StreamWriter class being created, initialized with the already set up fields and options from the FileStream instance named FileText.

    It looks like the reason is because you're being allowed to pass a text Encoding parameter, and the StreamWriter exposes a Constructor overload that accepts an encoding parameter too, as well as buffered IO.  Another way to write the same code would require many more lines.

            public static void AppendText(string path, string contenidos, Encoding encoding)
            {
                    FileStream FileText = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    // Set up a data buffer
                    byte[] encodedBuffer = encoding.GetBytes(contenidos);
                    // Ensure the file writeout cursor is at the end of the file    
                    if (FileText.Length > 0) { FileText.Position = FileText.Length - 1; }
                    // Ensure the file is big enough to accept appended writes
                    FileText.SetLength((FileText.Length + encodedBuffer.Length) - 1);
    
                    // Now because of "buffersize" we have to write a whole bunch of code to emulate a buffer
                    byte[] writeBuffer = new byte[1024];
                    int encodingCursor = 0;
                    do
                    {
                        // Each pass we need to make sure the "writeBuffer" is of adequate size but not too much size
                        // alternately, we could 0-fill the whole buffer every pass just to make sure we got a cleanly
                        // buffered copy.
                        if (writeBuffer.Length > (encodedBuffer.Length - encodingCursor))
                        {
                            // Whenever the remaining data to write is less than the writeBuffer size, shrink the 
                            // write buffer to fit
                            writeBuffer = new byte[(encodedBuffer.Length - encodingCursor)];
                        }
                        // Finally copy the needed data from the encoding buffer
                        Array.Copy(encodedBuffer, encodingCursor, writeBuffer, 0, writeBuffer.Length);
    
                        // Finally we can write the encoded text data
                        FileText.Write(writeBuffer, 0, writeBuffer.Length);
                        // Increment the encode cursor
                        encodingCursor += writeBuffer.Length;
    
                        // Keep looping until the encodingCursor is past the end of encoded data
                    } while (encodingCursor < encodedBuffer.Length);
    
                    FileText.Close();
                    FileText.Dispose();
                    FileText = null;
                    writeBuffer = null;
                    encodedBuffer = null;
            }

    So it's easy to see why someone would opt for the cleaner handoff to a StreamWriter rather than do it all themselves, right?  On top of that, we would hope that the DotNET Library was compiled to native code so it'd do all this junk we're doing a whole lot faster.

    There are other significant issues with your original code.  You're testing if the path already exists, when FileMode.Append should create the file if it doesn't exist.  This may be desired behavior, but just hamstrings your functionality and I can't think of a good reason to do that.  In addition, Append mode allows only FileAccess.Write, never Read, so you'd get an exception trying to instantiate the FileStream.  Perhaps the "snippets" project I use to write these demonstrations uses a different DotNET version than you have, which could explain it if this line of code works for you but not for me.


    It never hurts to try. In the worst-case scenario, you'll learn something.


    Andrew B. Painter, aka MR BS

    The code above is another example of your stupidity!

    You don't know what you are doing, but I am able to detect what 99.99% of members of this forum is not.

    The file you write is valid, but the data it contains gets corrupted!

    Do you know why? No?

    So, let me tell you, MR BS: you are another rubbish# coder in this forum; the result is that, every time you write bytes in the buufer, the previous buffer gets corrupted! The more you write, the more it will be corrupted.

    This corruption is caused by this statement:

        if (FileText.Length > 0) { FileText.Position = FileText.Length - 1; }

    As you see MR BS, you're an ignorant ssa eloh and pretender.

        ... and rubbish# coder.

    P.S.: if you don't like the way I treat you, ask the manager of these mvps to ban my account; if you don't succeed, this means my treatment to you, is correct!


    • Edited by ritehere44 Saturday, December 8, 2018 6:43 AM
    Saturday, December 8, 2018 6:42 AM


  • I take it that you stalk people across multiple threads often, derail threads with petulant flamewars, and have never been banned from MSDN Forums for it.  Also that you're the type who feels better about being unemployable by repeating belittling statements to your betters that someone else once said to you. 

    MR BS, I told you are an ssa eloh!

        ... and a rubbish# coder.

    Finally, please detail the nature of the corruption.  Explain what that line of code should be, and what the difference is between your version and mine.  MSDN readers deserve to know what the right way is!




    You don't know where the stream end, idiot! Just that, dude.

    Get back to school.

    P.S.: if you don't like the way I treat you, ask the manager of these mvps to ban my account; if you don't succeed, this means my treatment to you, is correct!


    • Edited by ritehere44 Saturday, December 8, 2018 7:08 AM
    Saturday, December 8, 2018 7:07 AM
  • I take it that you stalk people across multiple threads often, derail threads with petulant flamewars, and have never been banned from MSDN Forums for it. 

    Oh, @RiteHere has been banned many, many times! He manages to keep coming back, somehow.

    But, @Andrew … you've had a few pretty bad flame-wars yourself in other threads in the past few days. You've got to ignore this kind of behavior and hope the offending people get banned. If you fan the flames (with bad language or name-calling), you'll end up getting banned too. That was not a threat, I can't ban anybody, I just wanted you to be aware that if flamers and trolls are reported to the "powers that be", they can ban people.

    We should all strive to maintain professionalism here on the forums and not get sucked into fights. I try to (although sometimes I get a bit frustrated).


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Saturday, December 8, 2018 3:23 PM
    Moderator
  • You misunderstood me, Andrew. I can't ban anyone ... Moderators do not have that power. My intent was only to say that it's best to avoid flame-wars if possible. Someone has to be the "grown-up".  ;0)

    I understand your desire to provide correct and helpful replies to the OP. We all should strive for that and those that don't should be called out on it when they're wrong ... *BUT* in a professional and non-provoking manner! Don't be sucked into name-calling, no matter how many times they do it to you.

    And, believe it or not, sometimes those people actually post valid answers, marked as an answer by an OP and without any name-calling throughout the entire thread. To be honest, though, it seems like the mud-slinging is more prevalent than the answers (at least in the Forums I follow).


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Saturday, December 8, 2018 5:58 PM
    Moderator