diff --git a/lib/file.cpp b/lib/file.cpp
index 47b366f..4c3f22b 100644
--- a/lib/file.cpp
+++ b/lib/file.cpp
@@ -1,11 +1,19 @@
 #include "file.h"
 
-#include "util.h"
-
 namespace si {
 
 bool File::Open(const char *c, Mode mode)
 {
+#ifdef _WIN32
+  m_Handle = CreateFileA(c,
+                         mode == Read ? GENERIC_READ : GENERIC_WRITE,
+                         FILE_SHARE_READ,
+                         NULL,
+                         mode == Read ? OPEN_EXISTING : CREATE_NEW,
+                         FILE_ATTRIBUTE_NORMAL,
+                         NULL);
+  return m_Handle != INVALID_HANDLE_VALUE;
+#else
   std::ios::openmode m = std::ios::binary;
 
   if (mode == Read) {
@@ -21,49 +29,74 @@ bool File::Open(const char *c, Mode mode)
   }
 
   return false;
+#endif
 }
 
 #ifdef _WIN32
 bool File::Open(const wchar_t *c, Mode mode)
 {
-  std::ios::open_mode m = std::ios::binary;
-
-  if (mode == Read) {
-    m |= std::ios::in;
-  } else {
-    m |= std::ios::out;
-  }
-
-  m_Stream.open(c, m);
-  if (m_Stream.good() && m_Stream.is_open()) {
-    m_Mode = mode;
-    return true;
-  }
-
-  return false;
+  m_Handle = CreateFileW(c,
+                         mode == Read ? GENERIC_READ : GENERIC_WRITE,
+                         FILE_SHARE_READ,
+                         NULL,
+                         mode == Read ? OPEN_EXISTING : CREATE_NEW,
+                         FILE_ATTRIBUTE_NORMAL,
+                         NULL);
+  return m_Handle != INVALID_HANDLE_VALUE;
 }
 #endif
 
 size_t File::pos()
 {
+#ifdef _WIN32
+  DWORD high = 0;
+  DWORD low = SetFilePointer(m_Handle, 0, &high, FILE_CURRENT);
+  return (high << 32) | low;
+#else
   if (m_Mode == Read) {
     return m_Stream.tellg();
   } else {
     return m_Stream.tellp();
   }
+#endif
 }
 
 size_t File::size()
 {
+#ifdef _WIN32
+  DWORD high;
+  DWORD low = GetFileSize(m_Handle, &high);
+  return high << 32 | low;
+#else
   size_t before = pos();
   seek(0, SeekEnd);
   size_t sz = pos();
   seek(before, SeekStart);
   return sz;
+#endif
 }
 
 void File::seek(size_t p, SeekMode s)
 {
+#ifdef _WIN32
+  DWORD high = p >> 32;
+  DWORD low = p;
+
+  DWORD m;
+  switch (s) {
+  case SeekStart:
+    m = FILE_BEGIN;
+    break;
+  case SeekCurrent:
+    m = FILE_CURRENT;
+    break;
+  case SeekEnd:
+    m = FILE_END;
+    break;
+  }
+
+  SetFilePointer(m_Handle, low, &high, m);
+#else
   std::ios::seekdir d;
 
   switch (s) {
@@ -83,30 +116,42 @@ void File::seek(size_t p, SeekMode s)
   } else {
     m_Stream.seekp(p, d);
   }
-}
-
-bool File::atEnd()
-{
-  return !m_Stream.good();
+#endif
 }
 
 void File::Close()
 {
+#ifdef _WIN32
+  CloseHandle(m_Handle);
+#else
   m_Stream.close();
+#endif
 }
 
 size_t File::ReadData(void *data, size_t size)
 {
+#ifdef _WIN32
+  DWORD r;
+  ReadFile(m_Handle, data, size, &r, NULL);
+  return r;
+#else
   size_t before = this->pos();
   m_Stream.read((char *) data, size);
   return this->pos() - before;
+#endif
 }
 
 size_t File::WriteData(const void *data, size_t size)
 {
+#ifdef _WIN32
+  DWORD w;
+  WriteFile(m_Handle, data, size, &w, NULL);
+  return w;
+#else
   size_t before = this->pos();
   m_Stream.write((const char *) data, size);
   return this->pos() - before;
+#endif
 }
 
 uint8_t FileBase::ReadU8()
@@ -232,11 +277,6 @@ void MemoryBuffer::seek(size_t p, SeekMode s)
   }
 }
 
-bool MemoryBuffer::atEnd()
-{
-  return m_Position == m_Internal.size();
-}
-
 size_t MemoryBuffer::ReadData(void *data, size_t size)
 {
   size = std::min(size, m_Internal.size() - m_Position);
diff --git a/lib/file.h b/lib/file.h
index 0c62e19..0e7c95d 100644
--- a/lib/file.h
+++ b/lib/file.h
@@ -1,7 +1,11 @@
 #ifndef FILE_H
 #define FILE_H
 
+#ifdef _WIN32
+#include <Windows.h>
+#else
 #include <fstream>
+#endif
 
 #include "types.h"
 
@@ -51,7 +55,7 @@ public:
   virtual size_t pos() = 0;
   virtual size_t size() = 0;
   virtual void seek(size_t p, SeekMode s = SeekStart) = 0;
-  virtual bool atEnd() = 0;
+  LIBWEAVER_EXPORT bool atEnd() { return pos() == size(); }
 
 };
 
@@ -72,14 +76,17 @@ public:
   virtual size_t pos();
   virtual size_t size();
   virtual void seek(size_t p, SeekMode s = SeekStart);
-  virtual bool atEnd();
 
   virtual void Close();
   virtual size_t ReadData(void *data, size_t size);
   virtual size_t WriteData(const void *data, size_t size);
 
 private:
+#ifdef _WIN32
+  HANDLE m_Handle;
+#else
   std::fstream m_Stream;
+#endif
   Mode m_Mode;
 
 };
@@ -93,7 +100,6 @@ public:
   LIBWEAVER_EXPORT virtual size_t pos();
   LIBWEAVER_EXPORT virtual size_t size();
   LIBWEAVER_EXPORT virtual void seek(size_t p, SeekMode s = SeekStart);
-  LIBWEAVER_EXPORT virtual bool atEnd();
 
   const bytearray &data() const { return m_Internal; }