Do not truncate file on failed flush

- fixes #548
diff --git a/CHANGES.md b/CHANGES.md
index 0472b85..455a8b4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -4,6 +4,8 @@
 ## Version 4.2.0 (as yet unreleased)
 
 #### Fixes
+  * do not truncate file on failed flush
+   (see [#548](../../issues/548))
   * suppress deprecation warnings while collecting modules
    (see [#542](../../issues/542))
   * add support for `os.truncate` and `os.ftruncate`
diff --git a/pyfakefs/fake_filesystem.py b/pyfakefs/fake_filesystem.py
index 81ab908..a2487fd 100644
--- a/pyfakefs/fake_filesystem.py
+++ b/pyfakefs/fake_filesystem.py
@@ -384,11 +384,11 @@
         changed = self._byte_contents != contents
         st_size = len(contents)
 
-        if self._byte_contents:
-            self.size = 0
         current_size = self.st_size or 0
         self.filesystem.change_disk_usage(
             st_size - current_size, self.name, self.st_dev)
+        if self._byte_contents:
+            self.size = 0
         self._byte_contents = contents
         self.st_size = st_size
         self.epoch += 1
diff --git a/pyfakefs/tests/fake_open_test.py b/pyfakefs/tests/fake_open_test.py
index fc343e0..e684f07 100644
--- a/pyfakefs/tests/fake_open_test.py
+++ b/pyfakefs/tests/fake_open_test.py
@@ -918,6 +918,26 @@
             with self.open(self.os.devnull) as f:
                 self.assertEqual('', f.read())
 
+    def test_failed_flush_does_not_truncate_file(self):
+        # regression test for #548
+        self.skip_real_fs()  # cannot set fs size in real fs
+        self.filesystem.set_disk_usage(100)
+        self.os.makedirs("foo")
+        file_path = self.os.path.join('foo', 'bar.txt')
+        with self.open(file_path, 'wb') as f:
+            f.write(b'a' * 50)
+            f.flush()
+            with self.open(file_path, "rb") as r:
+                x = r.read()
+                self.assertTrue(x.startswith(b'a' * 50))
+            with self.assertRaises(OSError):
+                f.write(b'b' * 200)
+                f.flush()
+            with self.open(file_path, "rb") as r:
+                x = r.read()
+                self.assertTrue(x.startswith(b'a' * 50))
+            f.truncate(50)
+
 
 class RealFileOpenTest(FakeFileOpenTest):
     def use_real_fs(self):