diff --git a/SabreTools.Library/Writers/IniWriter.cs b/SabreTools.Library/Writers/IniWriter.cs
new file mode 100644
index 00000000..a2e3d1b4
--- /dev/null
+++ b/SabreTools.Library/Writers/IniWriter.cs
@@ -0,0 +1,101 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace SabreTools.Library.Writers
+{
+ public class IniWriter : IDisposable
+ {
+ ///
+ /// Internal stream writer for outputting
+ ///
+ private StreamWriter sw;
+
+ ///
+ /// Constructor for writing to a file
+ ///
+ public IniWriter(string filename)
+ {
+ sw = new StreamWriter(filename);
+ }
+
+ ///
+ /// Consturctor for writing to a stream
+ ///
+ public IniWriter(Stream stream, Encoding encoding)
+ {
+ sw = new StreamWriter(stream, encoding);
+ }
+
+ ///
+ /// Write a section tag
+ ///
+ public void WriteSection(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ throw new ArgumentException(nameof(value));
+
+ sw.WriteLine($"[{value.TrimStart('[').TrimEnd(']')}");
+ }
+
+ ///
+ /// Write a key value pair
+ ///
+ public void WriteKeyValuePair(string key, string value)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ throw new ArgumentException(nameof(key));
+
+ if (value == null)
+ value = string.Empty;
+
+ sw.WriteLine($"{key}={value}");
+ }
+
+ ///
+ /// Write a comment
+ ///
+ public void WriteComment(string value)
+ {
+ if (value == null)
+ value = string.Empty;
+
+ sw.WriteLine($";{value}");
+ }
+
+ ///
+ /// Write a generic string
+ ///
+ public void WriteString(string value)
+ {
+ if (value == null)
+ value = string.Empty;
+
+ sw.Write(value);
+ }
+
+ ///
+ /// Write a newline
+ ///
+ public void WriteLine()
+ {
+ sw.WriteLine();
+ }
+
+ ///
+ /// Flush the underlying writer
+ ///
+ public void Flush()
+ {
+ sw.Flush();
+ }
+
+ ///
+ /// Dispose of the underlying writer
+ ///
+ public void Dispose()
+ {
+ sw.Dispose();
+ }
+ }
+}