1

Hello I have been following numerous tutorials online for a new project I'm working on. I am obtaining my data from filestream and I'm getting an out of memory exception at this line:

byte[] buffer = new byte[(int)sfs.Length];

What I'm doing is immediately taking the byte array and then wanting to save it to the disc. If there is not an easy way to avoid the system out of memory exception, is there a way to write to disc from the sqlFileStream avoiding creating a new byte array?

        string cs = @”Data Source=<your server>;Initial Catalog=MyFsDb;Integrated Security=TRUE”;
        using (SqlConnection con = new SqlConnection(cs))
        {

            con.Open();
            SqlTransaction txn = con.BeginTransaction();
            string sql = “SELECT fData.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), fName FROM MyFsTable”;
            SqlCommand cmd = new SqlCommand(sql, con, txn);
            SqlDataReader rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                string filePath = rdr[0].ToString();
                byte[] objContext = (byte[])rdr[1];
                string fName = rdr[2].ToString();

                SqlFileStream sfs = new SqlFileStream(filePath, objContext, System.IO.FileAccess.Read);

                **byte[] buffer = new byte[(int)sfs.Length];**
                sfs.Read(buffer, 0, buffer.Length);
                sfs.Close();


                string filename = @”C:\Temp\” + fName;

                System.IO.FileStream fs = new System.IO.FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write);
                fs.Write(buffer, 0, buffer.Length);
                fs.Flush();
                fs.Close();
            }

            rdr.Close();
            txn.Commit();
            con.Close();
        }
    }
Meya
  • 21
  • 2
  • One of the points of a stream is that you can get the data one byte at a time or a chunk of bytes at a time. That means that you can read your data in, for instance, chunks of 1000 bytes and save it to disc using a `FileStream` one chunk at a time too. You still use a byte array but a much smaller one that you refill over and over until there's no data left. – jmcilhinney Feb 24 '17 at 02:38

1 Answers1

0

Here's a method that can be used to read bytes from one Stream to another Stream without regard for what type of Stream they each are.

Public Sub CopyStream(source As Stream, destination As Stream, Optional blockSize As Integer = 1024)
    Dim buffer(blockSize - 1) As Byte

    'Read the first block.'
    Dim bytesRead = source.Read(buffer, 0, blockSize)

    Do Until bytesRead = 0
        'Write the current block.'
        destination.Write(buffer, 0, bytesRead)

        'Read the next block.'
        bytesRead = source.Read(buffer, 0, blockSize)
    Loop
End Sub
Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • OK, I got to this question via the VB.NET tag and, after writing that code, I just realised that your code is C#. Don't do that again please. As you used the VB.NET tag, I'm leaving my VB.NET code there and you can convert it for yourself. – jmcilhinney Feb 24 '17 at 02:46
  • Funny thing is I actually need it in VB.NET but I just had an example in C#. I can easily convert between the two. Sorry for that. – Meya Feb 24 '17 at 02:52
  • OK, so then I will add that you can just call that method and pass in your `SqlFileStream` as the `source` and a `FileStream` object as the `destination`. I would suggest creating both `Using` statements so that they are implicitly closed at the end of the block. – jmcilhinney Feb 24 '17 at 03:06
  • Thank you SO much, I had no idea I could do something like this and it's working beautifully. You rock!!!!!! – Meya Feb 24 '17 at 03:14