Unfortunately my only code sample is in VB.NET. If you like to examine the full source, see my GitHub repository and full explanation in this Microsoft article.
Here is the core code translated from VB where line 80 is the key. What this does is ensures the temp file is deleted and that the only reason it would not be deleted is if the computer power was turned off before the app can close.
using System;
using System.IO;
using System.Text;
using DeleteFileOnClose.LanguageExtensions;
using DeleteFileOnClose.Modules;
namespace Classes
{
public class FileOperations
{
public event PeekEventHandler PeekEventHandler;
public event CustomersEventHandler CustomersEventHandler;
private FileStream _creator1;
/// <summary>
/// Setup FileStream with a random file name marked
/// to remove on app crash or normal close of app.
/// </summary>
public FileOperations()
{
_creator1 = FileStreamDeleteOnClose(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "K1".GenerateRandomXmlFile(5)));
}
public void Crash(string line)
{
var fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Crashed.txt");
try
{
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter fw = new StreamWriter(fs))
{
fw.Write(line);
}
}
Environment.FailFast(null);
//
// never get here
//
var crashVar = int.Parse(line);
File.Delete(fileName);
}
catch (Exception ex)
{
//
// never get here
//
if (File.Exists(fileName))
{
File.Delete(fileName);
}
}
}
public void QuickUse(List<Person> peopleList, bool failFast = false)
{
var fileName = Path.GetTempFileName();
if (failFast)
{
Console.WriteLine(fileName);
}
if (PeekEventHandler != null)
PeekEventHandler(this, new PeekArgs($"Temporary file name: {fileName}"));
if (PeekEventHandler != null)
PeekEventHandler(this, new PeekArgs(""));
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose))
{
using (var streamWriter = new StreamWriter(fileStream))
{
//
// Write each person comma delimited
//
for (int index = 0; index < peopleList.Count; index++)
{
if (index == 1 && failFast)
{
Console.WriteLine("Fail");
Environment.FailFast(null);
}
streamWriter.WriteLine($"{peopleList[index].FirstName},{peopleList[index].LastName}");
}
streamWriter.Flush();
//
// Read data back
//
StreamReader streamReader = null;
streamReader = new StreamReader(fileStream);
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);
while (streamReader.Peek() > -1)
{
var nameParts = streamReader.ReadLine().Split(',');
if (PeekEventHandler != null)
PeekEventHandler(this, new PeekArgs($"{nameParts[0]} - {nameParts[1]}"));
}
}
}
}
/// <summary>
/// Initial population of file
/// </summary>
public void PopulateTempFile()
{
XDocument xmlData = System.Xml.Linq.XElement.Parse("<?xml version=\"1.0\" standalone=\"yes\"?><Customers><Customer><CustomerID>100</CustomerID><CompanyName>Alfreds Futterkiste</CompanyName></Customer><Customer><CustomerID>101</CustomerID><CompanyName>Ana Trujillo Emparedados y helados</CompanyName></Customer><Customer><CustomerID>102</CustomerID><CompanyName>Bilido Comidas preparadas</CompanyName></Customer><Customer><CustomerID>103</CustomerID><CompanyName>Centro comercial Moctezuma</CompanyName></Customer></Customers>");
byte[] byteArray = Encoding.ASCII.GetBytes(xmlData.ToString());
_creator1.Write(byteArray, 0, byteArray.Length);
}
/// <summary>
/// Add a new Customer to the file then read the
/// file contents back
/// </summary>
/// <param name="newCustomer"></param>
public void AddNewCustomer(Customer newCustomer)
{
if (_creator1.Length == 0)
{
PopulateTempFile();
}
_creator1.Position = 0;
StreamReader streamReader = null;
streamReader = new StreamReader(_creator1);
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);
StringBuilder customerDataBuilder = new StringBuilder();
while (streamReader.Peek() > -1)
{
customerDataBuilder.Append(streamReader.ReadLine());
}
var customersLambdaTyped = (
from customer in XDocument.Parse(customerDataBuilder.ToString()).Descendants("Customer")
select customer).Select((customer) =>
{
return new Customer
{
Name = customer.Elements("CompanyName").Value,
Identifier = Convert.ToInt32(customer.Elements("CustomerID").Value)
};
}).ToList();
//
// Get last identifier and increment by 1
// Since we have an exclusive lock there are no
// issues of colliding with another section of code
// grabbing the same identifier
//
var id = customersLambdaTyped.Select((customer) => customer.Identifier).Max() + 1;
newCustomer.Identifier = id;
//
// Add customer to existing list
//
customersLambdaTyped.Add(newCustomer);
//
// Transform to XML using xml literals and embedded expressions
//
XDocument doc = System.Xml.Linq.XElement.Parse("<?xml version=\"1.0\" standalone=\"yes\"?><Customers>" +
from currentCustomer in customersLambdaTyped
select System.Xml.Linq.XElement.Parse("<Customer><CustomerID>" + currentCustomer.Identifier + "</CustomerID><CompanyName>" + currentCustomer.Name + "</CompanyName></Customer>") + "</Customers>");
doc.Declaration.Version = "1.0";
doc.Declaration.Encoding = "utf-8";
//
// Rewrite the file rather than appending
//
byte[] byteArray = Encoding.ASCII.GetBytes(doc.ToString());
_creator1.SetLength(0);
_creator1.Write(byteArray, 0, byteArray.Length);
ExamineCustomersFromXmlFile();
}
public void ExamineCustomersFromXmlFile()
{
if (_creator1.Length == 0)
{
PopulateTempFile();
}
//
// Rewind to start of temporary file
//
_creator1.Position = 0;
//
// Read data from temporary file into a StringBuilder
// to parse into either a anonymous type or strong typed
// list.
//
StreamReader streamReader = null;
streamReader = new StreamReader(_creator1);
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);
StringBuilder customerDataBuilder = new StringBuilder();
while (streamReader.Peek() > -1)
{
customerDataBuilder.Append(streamReader.ReadLine());
}
//
// Example of reading data anonymously and strong typed
//
var customersLinqAnonymous = (
from customer in XDocument.Parse(customerDataBuilder.ToString()).Descendants("Customer")
select new
{
Name = customer.Elements("CompanyName").Value,
Identifier = Convert.ToInt32(customer.Elements("CustomerID").Value)
}).ToList();
var customersLambdaTyped = (
from customer in XDocument.Parse(customerDataBuilder.ToString()).Descendants("Customer")
select customer).Select((customer) =>
{
return new Customer
{
Name = customer.Elements("CompanyName").Value,
Identifier = Convert.ToInt32(customer.Elements("CustomerID").Value)
};
}).ToList();
if (CustomersEventHandler != null)
CustomersEventHandler(this, new CustomerArgs(customersLambdaTyped));
}
}
}