Opening and existing file in read only mode and then loading the contents into memory is supposed to be one of the easiest things to do using C#. It turns out that is not; especially in high capacity situations (asp.net core webserver) or for cases when reading large files is necessary.
The solution provided consists of two functions; a read bytes function and a read text function. Both functions are async and the read bytes function DOES NOT implement the using clause; as that relies on garbage collection on a stream which is not timely enough for high capacity environments.
Note too that the entire contents of the file are read into memory. This is required for encryption, decryption purposes, image processing, etc. Note too that the sequential steps are shown. ie it is not a one line cryptic programmer chest thump statement. Also, please don't confuse this with FileStreamResult as that is a totally different beast. The code is shown below.
// -------------------------------------------------------------------------------
// This function reads bytes from a file and returns a byte array containing the
// the full file contents
// -------------------------------------------------------------------------------
public async Task<byte[]> ReadBytesAsync(string Filename, int BufSize = 64 * 1024)
{
// dim the byte array
byte[] rt = new byte[0];
// define the filestream
FileStream fs = null;
// set up a try catch block just in case
try
{
// open the file stream
fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read, BufSize);
// define an array
byte[] b = new byte[fs.Length];
// read bytes
int bytesRead = fs.Read(b);
// read the bytes from the file stream
while (bytesRead > 0)
{
// get the current length of the return buffer
int curRtLength = rt.Length;
// redim the return buffer to the current length plus the bytes read
Array.Resize(ref rt, curRtLength + bytesRead);
// copy the buf b to rt.
Array.Copy(b, 0, rt, curRtLength, bytesRead);
// read more from the stream
bytesRead = fs.Read(b);
}
}
catch (Exception)
{
rt = new byte[0];
}
// if the filestream is not null, then close, dispose.
if (fs != null)
{
// close it.
fs.Close();
// dispose
await fs.DisposeAsync();
// null it out
fs = null;
}
// return the byte array
return rt;
}
Shown below is the Read Text Async function. This calls the ReadBytesAsync function above. Note that this function has an encoding parameter. This is important because one might be reading ascii text, Unicode, etc.
// ---------------------------------------------------------------------------------------------
// This function reads a file from the file systems and returns a encoded string representation
// of the file.
// ---------------------------------------------------------------------------------------------
public async Task<string> ReadTextAsync(string fn, Encoding enc = null, int BufSize = 64 * 1024)
{
// deault to empty string
string rt = "";
// default the encoding. Note, UTF8 specified.
Encoding encoding = Encoding.UTF8;
// read the encoding parameter (enc)
if (enc != null) {
// set the encoding
encoding = enc;
}
// quick file exists check. optional.
if (File.Exists(fn))
{
// set the byte array returned.
byte[] b = await ReadBytesAsync(fn, BufSize);
// check for null
if (b != null)
{
// check for length
if (b.Length > 0)
{
// get the string from the byte array
rt = encoding.GetString(b);
}
}
}
// return the string
return rt;
}
Usage:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
public async Task<byte[]> GetFileBytes(string fileName)
{
return await ReadBytesAsync(fileName);
}
public async Task<string> GetFileAsString(string fileName, Encoding encoding)
{
return await ReadTextAsync(fileName, encoding);
}
I hope you find it helpful.
Paul F. Sirpenski
Personal Open Source Directory Of Paul F. Sirpenski |
|
ASP.NET Core
Open Source directory Of the Microsoft Asp.Net Core project. |