diff --git a/athenasub/athenasub_2008.vcproj b/athenasub/athenasub_2008.vcproj
index c714e22c8859689acd2d06fb2742461b4724ba54..d4f569ed24d08c1eb1eda06338715faf5ad134e0 100644
--- a/athenasub/athenasub_2008.vcproj
+++ b/athenasub/athenasub_2008.vcproj
@@ -328,7 +328,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\include\aegilib\format_manager.h"
+				RelativePath=".\src\format_manager.h"
 				>
 			</File>
 			<Filter
@@ -447,6 +447,14 @@
 		<Filter
 			Name="File IO"
 			>
+			<File
+				RelativePath=".\src\reader.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\reader.h"
+				>
+			</File>
 			<File
 				RelativePath=".\src\text_file_reader.cpp"
 				>
@@ -487,6 +495,14 @@
 				RelativePath=".\src\text_writer.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\writer.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\writer.h"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>
diff --git a/athenasub/include/athenasub/interfaces.h b/athenasub/include/athenasub/interfaces.h
index 98c4ab09241cbb7668ab047931a5e567effd8e9d..7650aa55ddfe5d1c2e4436300c3625610888049a 100644
--- a/athenasub/include/athenasub/interfaces.h
+++ b/athenasub/include/athenasub/interfaces.h
@@ -49,6 +49,8 @@ namespace Athenasub {
 
 	// Prototypes
 	class Range;
+	class Reader;
+	class Writer;
 	class ISelection;
 	class IController;
 	class IView;
@@ -113,7 +115,7 @@ namespace Athenasub {
 		virtual void DispatchNotifications(Notification notification) const = 0;
 
 		virtual void Clear() = 0;
-		virtual void Load(wxInputStream &input,Format format=Format(),const String encoding="") = 0;
+		virtual void Load(Reader &input,Format format=Format()) = 0;
 
 		virtual Section AddSection(String name) = 0;
 		virtual Section GetMutableSection(String name) = 0;
@@ -125,7 +127,7 @@ namespace Athenasub {
 		virtual Controller CreateController() = 0;
 		virtual void AddListener(View listener) = 0;
 
-		virtual void Save(wxOutputStream &output,Format format=Format(),const String encoding="UTF-8") const = 0;
+		virtual void Save(Writer &output,Format format=Format()) const = 0;
 
 		virtual String GetUndoMessage(const String owner="") const = 0;
 		virtual String GetRedoMessage(const String owner="") const = 0;
@@ -316,6 +318,9 @@ namespace Athenasub {
 
 		virtual Dialogue CreateDialogue() const = 0;
 		virtual Style CreateStyle() const = 0;
+
+		virtual bool IsBinary() const = 0;
+		virtual float CanReadFile(Reader &reader) const = 0;	// Should return a float from 0.0f to 1.0f indicating how certain it is that it can read it
 	};
 
 
@@ -324,8 +329,8 @@ namespace Athenasub {
 	public:
 		virtual ~IFormatHandler() {}
 
-		virtual void Load(IModel &model,wxInputStream &file,const String encoding) = 0;
-		virtual void Save(const IModel &model,wxOutputStream &file,const String encoding) const = 0;
+		virtual void Load(IModel &model,Reader &file) = 0;
+		virtual void Save(const IModel &model,Writer &file) const = 0;
 	};
 
 
diff --git a/athenasub/src/controller.cpp b/athenasub/src/controller.cpp
index ac50e7684b7e089f9b84b17ad2a7f20fa3062fd1..82c4926da18c0293ddca7e4a298a09187ed4b404 100644
--- a/athenasub/src/controller.cpp
+++ b/athenasub/src/controller.cpp
@@ -38,6 +38,8 @@
 #include "actionlist.h"
 #include "format_manager.h"
 #include "selection.h"
+#include "reader.h"
+#include "writer.h"
 using namespace Athenasub;
 
 
@@ -61,9 +63,24 @@ ActionList CController::CreateActionList(const String title,const String owner,b
 // Load a file
 void CController::LoadFile(const String filename,const String encoding)
 {
-	const Format handler = FormatManager::GetFormatFromFilename(filename,true);
-	wxFFileInputStream stream(filename.GetWxString());
-	model->Load(stream,handler,encoding);
+	Reader reader(filename,encoding);
+	std::vector<Format> handlers = FormatManager::GetCompatibleFormatList(reader);
+	size_t len = handlers.size();
+	bool success = false;
+	for (size_t i=0;i<len;i++) {
+		try {
+			model->Load(reader,handlers[i]);
+			success = true;
+			break;
+		} catch (Athenasub::Exception &e) {
+			// Ignore exception
+			(void) e;
+		}
+	}
+
+	if (!success) {
+		THROW_ATHENA_EXCEPTION_MSG(Exception::No_Format_Handler,"Could not locate a suitable format handler.");
+	}
 }
 
 
@@ -71,9 +88,9 @@ void CController::LoadFile(const String filename,const String encoding)
 // Save a file
 void CController::SaveFile(const String filename,const String encoding)
 {
-	const Format handler = FormatManager::GetFormatFromFilename(filename,true);
-	wxFFileOutputStream stream(filename.GetWxString());
-	model->Save(stream,handler,encoding);
+	Format handler = FormatManager::GetFormatFromFilename(filename,true);
+	Writer writer(filename,encoding);
+	model->Save(writer,handler);
 }
 
 
diff --git a/athenasub/src/format_handler.h b/athenasub/src/format_handler.h
index 3b5f5e955f46ca547e032dda51772fd2ba749b0e..526c57f404344a98c57f3b6294ad0a1e974990fa 100644
--- a/athenasub/src/format_handler.h
+++ b/athenasub/src/format_handler.h
@@ -55,8 +55,8 @@ namespace Athenasub {
 	public:
 		//CFormatHandler(IModel& _model) : model(_model) {}
 
-		virtual void Load(IModel &model,wxInputStream &file,const String encoding) = 0;
-		virtual void Save(const IModel &model,wxOutputStream &file,const String encoding) const = 0;
+		virtual void Load(IModel &model,Reader &file) = 0;
+		virtual void Save(const IModel &model,Writer &file) const = 0;
 	};
 
 }
diff --git a/athenasub/src/format_manager.cpp b/athenasub/src/format_manager.cpp
index 9b7750203e385a17d89ac50b8002f04f6ca768d8..1d98b1f7e857b6204c7c13d01f6bb720cfdda87b 100644
--- a/athenasub/src/format_manager.cpp
+++ b/athenasub/src/format_manager.cpp
@@ -35,6 +35,8 @@
 
 #include "format_manager.h"
 #include "formats/format_ass.h"
+#include "reader.h"
+#include "text_reader.h"
 #include <wx/string.h>
 using namespace Athenasub;
 
@@ -56,9 +58,9 @@ void FormatManager::AddFormat(const Format format)
 // Initialize all built-in formats
 void FormatManager::InitializeFormats()
 {
-	formats.push_back(Format(new FormatASS()));
-	formats.push_back(Format(new FormatSSA()));
-	formats.push_back(Format(new FormatASS2()));
+	AddFormat(Format(new FormatASS()));
+	AddFormat(Format(new FormatSSA()));
+	AddFormat(Format(new FormatASS2()));
 }
 
 
@@ -80,7 +82,7 @@ int FormatManager::GetFormatCount()
 
 ////////////
 // By index
-const Format FormatManager::GetFormatByIndex(const int index)
+Format FormatManager::GetFormatByIndex(const int index)
 {
 	try {
 		return formats.at(index);
@@ -93,7 +95,7 @@ const Format FormatManager::GetFormatByIndex(const int index)
 
 ///////////////
 // By filename
-const Format FormatManager::GetFormatFromFilename(const String &filename,bool read)
+Format FormatManager::GetFormatFromFilename(const String &filename,bool read)
 {
 	size_t len = formats.size();
 	for (size_t i=0;i<len;i++) {
@@ -111,7 +113,7 @@ const Format FormatManager::GetFormatFromFilename(const String &filename,bool re
 
 //////////////////
 // By format name
-const Format FormatManager::GetFormatFromName(const String &name)
+Format FormatManager::GetFormatFromName(const String &name)
 {
 	size_t len = formats.size();
 	for (size_t i=0;i<len;i++) {
@@ -120,3 +122,35 @@ const Format FormatManager::GetFormatFromName(const String &name)
 	return Format();
 }
 
+
+///////////////////////////////////////////////////////
+// Get a list of all formats compatible with this file
+std::vector<Format> FormatManager::GetCompatibleFormatList(Reader &reader)
+{
+	// Find all compatible formats and store them with their certainty
+	std::vector<std::pair<float,Format> > results;
+	size_t len = formats.size();
+	for (size_t i=0;i<len;i++) {
+		reader.Rewind();
+		float certainty = formats[i]->CanReadFile(reader);
+		if (certainty > 0.0f) {
+			results.push_back(std::pair<float,Format>(certainty,formats[i]));
+		}
+	}
+
+	// Functor to sort them
+	struct Comp {
+		bool operator() (const std::pair<float,Format> &p1,const std::pair<float,Format> &p2) {
+			return p1.first > p2.first;
+		}
+	};
+
+	// Sort results and store them
+	sort(results.begin(),results.end(),Comp());
+	len = results.size();
+	std::vector<Format> finalResults;
+	for (size_t i=0;i<len;i++) {
+		finalResults.push_back(results[i].second);
+	}
+	return finalResults;
+}
diff --git a/athenasub/src/format_manager.h b/athenasub/src/format_manager.h
index 6ad5643a2c2c98a9301302f7837bb09c4cec5f90..1996cf4d02a2824a27fedbc0a925d9d632315ca2 100644
--- a/athenasub/src/format_manager.h
+++ b/athenasub/src/format_manager.h
@@ -38,6 +38,8 @@
 
 namespace Athenasub {
 
+	class Reader;
+
 	// Format manager class
 	class FormatManager {
 	private:
@@ -50,9 +52,10 @@ namespace Athenasub {
 		static void ClearFormats();
 
 		static int GetFormatCount();
-		static const Format GetFormatByIndex(const int index);
-		static const Format GetFormatFromFilename(const String &filename,bool read);
-		static const Format GetFormatFromName(const String &name);
+		static Format GetFormatByIndex(const int index);
+		static Format GetFormatFromFilename(const String &filename,bool read);
+		static Format GetFormatFromName(const String &name);
+		static std::vector<Format> GetCompatibleFormatList(Reader &reader);
 	};
 
 }
diff --git a/athenasub/src/formats/format_ass.cpp b/athenasub/src/formats/format_ass.cpp
index 9a99aecb4256edc2de7bece23ebcd1d73542be86..d8f23b79c880d6703a3fb803555bf663effbf310 100644
--- a/athenasub/src/formats/format_ass.cpp
+++ b/athenasub/src/formats/format_ass.cpp
@@ -39,7 +39,9 @@
 #include "format_ass_plain.h"
 #include "version.h"
 #include "../text_reader.h"
+#include "../reader.h"
 #include "../text_writer.h"
+#include "../writer.h"
 #include <iostream>
 #include <algorithm>
 #include <wx/tokenzr.h>
@@ -88,6 +90,19 @@ StringArray FormatASS2::GetWriteExtensions() const
 }
 
 
+
+//////////////////////////////////
+// Check if it can read this file
+float FormatASSFamily::CanReadFile(Reader &reader) const
+{
+	shared_ptr<TextReader> file = reader.GetTextReader();
+	if (!file->HasMoreLines()) return 0;
+	String line = file->ReadLineFromFile();
+	if (line == "[Script Info]") return 1;
+	return 0;
+}
+
+
 ///////////////
 // Constructor
 FormatHandlerASS::FormatHandlerASS(int version)
@@ -105,10 +120,10 @@ FormatHandlerASS::~FormatHandlerASS()
 
 ///////////////
 // Load a file
-void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encoding)
+void FormatHandlerASS::Load(IModel &model,Reader &file)
 {
-	// Make text file reader
-	shared_ptr<TextReader> reader = TextReader::GetReader(file,encoding);
+	// Get text file reader
+	shared_ptr<TextReader> reader = file.GetTextReader();
 
 	// Variables
 	int version = 1;
@@ -148,10 +163,10 @@ void FormatHandlerASS::Load(IModel &model,wxInputStream &file,const String encod
 
 /////////////////////
 // Save file to disc
-void FormatHandlerASS::Save(const IModel& model,wxOutputStream &file,const String encoding) const
+void FormatHandlerASS::Save(const IModel& model,Writer &file) const
 {
 	// Make text file writer
-	shared_ptr<TextWriter> writer = TextWriter::GetWriter(file,encoding);
+	shared_ptr<TextWriter> writer = file.GetTextWriter();
 
 	// Set up list of sections to write
 	StringArray sections;
diff --git a/athenasub/src/formats/format_ass.h b/athenasub/src/formats/format_ass.h
index 374a842209220012f7c0c4999f58d40d6c315cfc..dcbc9099a83a0825a976d4f801a9e6fc02f1f75c 100644
--- a/athenasub/src/formats/format_ass.h
+++ b/athenasub/src/formats/format_ass.h
@@ -62,8 +62,8 @@ namespace Athenasub {
 		FormatHandlerASS(int version);
 		~FormatHandlerASS();
 
-		void Load(IModel &model,wxInputStream &file,const String encoding);
-		void Save(const IModel &model,wxOutputStream &file,const String encoding) const;
+		void Load(IModel &model,Reader &file);
+		void Save(const IModel &model,Writer &file) const;
 	};
 
 	// Advanced Substation Alpha format base class
@@ -84,9 +84,11 @@ namespace Athenasub {
 
 		virtual int GetTimingPrecision() const { return 10; }
 		virtual int GetMaxTime() const { return 35999990; }
+		bool IsBinary() const { return false; }
 
 		Dialogue CreateDialogue() const { return Dialogue(new DialogueASS()); }
 		Style CreateStyle() const { return Style(new StyleASS()); }
+		float CanReadFile(Reader &reader) const;
 	};
 
 	// Substation Alpha
diff --git a/athenasub/src/model.cpp b/athenasub/src/model.cpp
index c46842c4cf2f58d0251183ba7c5a8a27183f8564..8137aae9e6f25d3cfb26d6342102ad5873999e94 100644
--- a/athenasub/src/model.cpp
+++ b/athenasub/src/model.cpp
@@ -109,7 +109,7 @@ void CModel::ProcessActionList(CActionList &_actionList,int type)
 
 //////////////////
 // Load subtitles
-void CModel::Load(wxInputStream &input,const Format _format,const String encoding)
+void CModel::Load(Reader &input,const Format _format)
 {
 	// Autodetect format
 	if (!_format) {
@@ -127,7 +127,7 @@ void CModel::Load(wxInputStream &input,const Format _format,const String encodin
 	Clear();
 
 	// Load
-	handler->Load(*this,input,encoding);
+	handler->Load(*this,input);
 
 	// Set the format
 	format = _format;
@@ -136,7 +136,7 @@ void CModel::Load(wxInputStream &input,const Format _format,const String encodin
 
 //////////////////
 // Save subtitles
-void CModel::Save(wxOutputStream &output,const Format _format,const String encoding) const
+void CModel::Save(Writer &output,const Format _format) const
 {
 	// Use another format
 	if (_format && _format != format) {
@@ -149,7 +149,7 @@ void CModel::Save(wxOutputStream &output,const Format _format,const String encod
 	if (!handler) THROW_ATHENA_EXCEPTION(Exception::No_Format_Handler);
 
 	// Load
-	handler->Save(*this,output,encoding);
+	handler->Save(*this,output);
 }
 
 
diff --git a/athenasub/src/model.h b/athenasub/src/model.h
index ceca0ccd50cc8ccb4fffe76c3f91c41ff7ec6db1..e6b264add94c0ef7333c560222b308bf2590dfa4 100644
--- a/athenasub/src/model.h
+++ b/athenasub/src/model.h
@@ -36,7 +36,6 @@
 #pragma once
 #include <list>
 #include <vector>
-#include <wx/wfstream.h>
 #include "athenasub.h"
 #include "actionlist.h"
 #include "section.h"
@@ -80,7 +79,7 @@ namespace Athenasub {
 		void DispatchNotifications(Notification notification) const;
 
 		void Clear();
-		void Load(wxInputStream &input,Format format=Format(),const String encoding="");
+		void Load(Reader &input,Format format=Format());
 
 		Section AddSection(String name);
 		Section GetMutableSection(String name);
@@ -94,7 +93,7 @@ namespace Athenasub {
 		Format GetFormat() const { return format; }
 
 		void AddListener(View listener);
-		void Save(wxOutputStream &output,Format format=Format(),const String encoding="UTF-8") const;
+		void Save(Writer &output,Format format=Format()) const;
 
 		ConstSection GetSection(String name) const;
 		ConstSection GetSectionByIndex(size_t index) const;
diff --git a/athenasub/src/reader.cpp b/athenasub/src/reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..177799fbb5cd09545de41136b619336405cb7c21
--- /dev/null
+++ b/athenasub/src/reader.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#include "reader.h"
+#include "text_reader.h"
+#include <wx/wfstream.h>
+using namespace Athenasub;
+
+
+Reader::Reader(String filename,String encoding)
+{
+	stream = shared_ptr<wxFFileInputStream>(new wxFFileInputStream(filename.GetWxString()));
+	text = TextReader::GetReader(*stream,encoding);
+}
+
+shared_ptr<TextReader> Athenasub::Reader::GetTextReader()
+{
+	return text;
+}
+
+void Reader::Rewind()
+{
+	text->Rewind();
+}
\ No newline at end of file
diff --git a/athenasub/src/reader.h b/athenasub/src/reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..168c8151df14c8d216483eb48df4b28256e0e6ff
--- /dev/null
+++ b/athenasub/src/reader.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#pragma once
+
+
+// Headers
+#include "athenasub.h"
+
+class wxFFileInputStream;
+namespace Athenasub {
+	class TextReader;
+
+	class Reader {
+	private:
+		shared_ptr<TextReader> text;
+		String filename;
+		shared_ptr<wxFFileInputStream> stream;
+
+	public:
+		Reader(String filename,String encoding="");
+
+		shared_ptr<TextReader> GetTextReader();
+		String GetFileName();
+		void Rewind();
+	};
+}
diff --git a/athenasub/src/section_entry_dialogue.h b/athenasub/src/section_entry_dialogue.h
index 5f4eb8bd06db8c76dca5a594d78c12e3c92fd78d..e54475c610e850775c23bf360561db4180da8cd1 100644
--- a/athenasub/src/section_entry_dialogue.h
+++ b/athenasub/src/section_entry_dialogue.h
@@ -44,8 +44,7 @@ namespace Athenasub {
 	// Dialogue class
 	class CDialogue : public IDialogue {
 	private:
-		static const bool dodgeWarning = true;
-		void ThrowUnsupported() const { if (dodgeWarning) THROW_ATHENA_EXCEPTION(Exception::Unsupported_Format_Feature); }
+#define ThrowUnsupported() THROW_ATHENA_EXCEPTION(Exception::Unsupported_Format_Feature)
 		static const String& EmptyString();
 
 	public:
diff --git a/athenasub/src/section_entry_style.h b/athenasub/src/section_entry_style.h
index 77be9c8234c5cb6181e2f97e882b4ee59939d284..10861323fbbe69b2939b59b584b535bf1bc14631 100644
--- a/athenasub/src/section_entry_style.h
+++ b/athenasub/src/section_entry_style.h
@@ -44,8 +44,7 @@ namespace Athenasub {
 	// Style class
 	class CStyle : public IStyle {
 	private:
-		static const bool dodgeWarning = true;
-		void ThrowUnsupported() const { if (dodgeWarning) THROW_ATHENA_EXCEPTION(Exception::Unsupported_Format_Feature); }
+		#define ThrowUnsupported() THROW_ATHENA_EXCEPTION(Exception::Unsupported_Format_Feature)
 
 	public:
 		// Destructor
diff --git a/athenasub/src/text_reader_cache.cpp b/athenasub/src/text_reader_cache.cpp
index 99dc79ef5ee32d76f8fc7dbf39ea874e1bb40df6..81189f084c17942a8afa363ab131693b63ff1073 100644
--- a/athenasub/src/text_reader_cache.cpp
+++ b/athenasub/src/text_reader_cache.cpp
@@ -48,7 +48,7 @@ Athenasub::TextReaderCache::TextReaderCache(shared_ptr<TextReader> src)
 String TextReaderCache::ReadLineFromFile()
 {
 	if (bufferPos == buffer.size()) {
-		LoadMore(1);
+		LoadMore(1000000);
 	}
 	if (bufferPos == buffer.size()) {
 		return "";
diff --git a/athenasub/src/writer.cpp b/athenasub/src/writer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3261ea8a4264672ea938fc3b2cb0350200d127c
--- /dev/null
+++ b/athenasub/src/writer.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#include "writer.h"
+#include "text_writer.h"
+#include <wx/wfstream.h>
+using namespace Athenasub;
+
+
+Writer::Writer(String filename,String encoding)
+{
+	stream = shared_ptr<wxFFileOutputStream>(new wxFFileOutputStream(filename.GetWxString()));
+	text = TextWriter::GetWriter(*stream,encoding);
+}
+
+
+shared_ptr<TextWriter> Writer::GetTextWriter()
+{
+	return text;
+}
diff --git a/athenasub/src/writer.h b/athenasub/src/writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..e54fd0eb299ad8b40b165d04f73141ba795b6087
--- /dev/null
+++ b/athenasub/src/writer.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#pragma once
+
+
+// Headers
+#include "athenasub.h"
+
+
+class wxFFileOutputStream;
+namespace Athenasub {
+	class TextWriter;
+
+	class Writer {
+	private:
+		shared_ptr<TextWriter> text;
+		shared_ptr<wxFFileOutputStream> stream;
+
+	public:
+		Writer(String filename,String encoding="");
+
+		shared_ptr<TextWriter> GetTextWriter();
+	};
+}
diff --git a/unit_test/unit_test.vcproj b/unit_test/unit_test.vcproj
index 5a7257d886597f9a8b211d9e47476e470c6d0198..fba87ae1e642ca7f9f6d9333ffd91d4b0a55cafa 100644
--- a/unit_test/unit_test.vcproj
+++ b/unit_test/unit_test.vcproj
@@ -61,6 +61,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
+				OutputFile="../../bin/unit_test_d.exe"
 				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
@@ -134,6 +135,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
+				OutputFile="../../bin/unit_test.exe"
 				LinkIncremental="1"
 				GenerateDebugInformation="true"
 				SubSystem="1"
@@ -161,6 +163,7 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
+				CommandLine=""
 			/>
 		</Configuration>
 	</Configurations>