diff --git a/KantaAsiakas.java b/KantaAsiakas.java
index e8835114110082f269eed1393fdee1f7e9cbe863..b9730f9c01b46aaeaa958e1dcdd954123d70cec7 100644
--- a/KantaAsiakas.java
+++ b/KantaAsiakas.java
@@ -15,4 +15,9 @@ public class KantaAsiakas extends Asiakas{
     public void setAlennusprosentti(int alennusprosentti) {
         this.alennusprosentti = alennusprosentti;
     }
+
+    @Override
+    public String toString() {
+        return super.toString() + ", alennusprosentti: " + alennusprosentti;
+    }
 }
diff --git a/Tuote.java b/Tuote.java
index 884187e925272df06dffc64b6e6a5a823cd8eaa6..36afbddb708f8df21f4651acb39c2709e65c1f64 100644
--- a/Tuote.java
+++ b/Tuote.java
@@ -1,4 +1,9 @@
-public class Tuote {
+import java.io.Serializable;
+
+public class Tuote implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
     private String nimi;
     private int saldo;
     private double hinta;
@@ -45,5 +50,10 @@ public class Tuote {
         if (hinta >= 0)
             this.hinta = hinta;
     }
+
+    @Override
+    public String toString() {
+        return nimi + " (" + hinta + " euroa), saldo: " + saldo;
+    }
 }
 
diff --git a/VerkkokauppaIO.java b/VerkkokauppaIO.java
index 7ece477638f92dfbe4305629740365af1bf4c584..0327f80555f5884b65f1917ceddff38d664cfbe4 100644
--- a/VerkkokauppaIO.java
+++ b/VerkkokauppaIO.java
@@ -1,6 +1,4 @@
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
+import java.io.*;
 import java.util.ArrayList;
 import java.util.Scanner;
 
@@ -13,10 +11,8 @@ import java.util.Scanner;
 public class VerkkokauppaIO {
 
     public static void main(String[] args) {
-        ArrayList<Asiakas> al = lueAsiakkaat("asiakkaat.csv");
-        for (Asiakas as : al) {
-            System.out.println(as);
-        }
+        // Tähän voi kirjoittaa koodia, jolla testata
+        // kirjoitus- ja lukumetodien toimintaa helposti
     }
 
     private static final String EROTIN = ";";
@@ -49,6 +45,12 @@ public class VerkkokauppaIO {
         return data;
     }
 
+    /**
+     * Kirjoittaa asiakaslistan annetun nimiseen tiedostoon.
+     *
+     * @param asiakasLista  lista kirjoitettavista asiakkaista.
+     * @param tiedostonNimi kirjoitettavan tiedoston nimi
+     */
     public static void kirjoitaAsiakkaat(ArrayList<Asiakas> asiakasLista,
                                          String tiedostonNimi) {
         String data = "";
@@ -98,4 +100,40 @@ public class VerkkokauppaIO {
         }
         return asiakkaat;
     }
+
+    /**
+     * Kirjoittaa tuotelistan annetun nimiseen tiedostoon.
+     *
+     * @param tuotelista    lista tuotteista
+     * @param tiedostonNimi kirjoitettavan tiedoston nimi
+     */
+    public static void kirjoitaTuotteet(ArrayList<Tuote> tuotelista, String tiedostonNimi) {
+        try (ObjectOutputStream oos =
+                     new ObjectOutputStream(
+                             new FileOutputStream(tiedostonNimi))) {
+            oos.writeObject(tuotelista);
+        } catch (IOException e) {
+            System.out.println("Tapahtui virhe: " + e);
+        }
+    }
+
+    /**
+     * Lukee tuotelistan tiedostosta
+     *
+     * @param tiedostonNimi tiedoston nimi
+     * @return listan tuotteita
+     */
+    public static ArrayList<Tuote> lueTuotteet(String tiedostonNimi) {
+        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(tiedostonNimi))) {
+            ArrayList<Tuote> tlista = (ArrayList<Tuote>) ois.readObject();
+            return tlista;
+        } catch (IOException e) {
+            System.out.println("Tapahtui virhe: " + e);
+        } catch (ClassNotFoundException e) {
+            // Tämä virhe tulee, jos luettu tieto ei ole yhteensopiva
+            // sen luokan kanssa, jonka tyyppiseksi se yritetään muuntaa
+            System.out.println("Tapahtui virhe: " + e);
+        }
+        return null;
+    }
 }
diff --git a/VirtuaalinenTuote.java b/VirtuaalinenTuote.java
index 8dc454ad6bd114865ba82c4d0a9ac11a90f21363..b89ceaa496181d319357f3ac1504da6a73f477dd 100644
--- a/VirtuaalinenTuote.java
+++ b/VirtuaalinenTuote.java
@@ -11,4 +11,9 @@ public class VirtuaalinenTuote extends Tuote {
         // tilaukseen
         return 1000;
     }
+
+    @Override
+    public String toString() {
+        return super.getNimi() + " (" + super.getHinta() + "), virtuaalinen tuote.";
+    }
 }
\ No newline at end of file
diff --git a/asiakkaat.csv b/asiakkaat.csv
deleted file mode 100644
index 84638ea1e5440e9c67f7d85b95a0631fe8b34b0e..0000000000000000000000000000000000000000
--- a/asiakkaat.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-12345;Antti Asiakas;10.0
-54321;Anna Asiakas;55.5
-99999;Keijo Keksitty;1000.0
\ No newline at end of file
diff --git a/out/production/oop-demo4-esimerkit/Tuote.class b/out/production/oop-demo4-esimerkit/Tuote.class
index 0f4366e0003bf8569a02d4bcd3784b14a8d04529..569fc21e049c8b3e9f348603194fe4ce453e1302 100644
Binary files a/out/production/oop-demo4-esimerkit/Tuote.class and b/out/production/oop-demo4-esimerkit/Tuote.class differ
diff --git a/out/production/oop-demo4-esimerkit/VerkkokauppaIO.class b/out/production/oop-demo4-esimerkit/VerkkokauppaIO.class
index e98deee2fbc1fe5ead5f5bd6b4dcc83bc26bb4f3..568611e6fb8e0f0b6ee66469ca45c292c77054e1 100644
Binary files a/out/production/oop-demo4-esimerkit/VerkkokauppaIO.class and b/out/production/oop-demo4-esimerkit/VerkkokauppaIO.class differ
diff --git a/out/production/oop-demo4-esimerkit/VirtuaalinenTuote.class b/out/production/oop-demo4-esimerkit/VirtuaalinenTuote.class
index bb7fb6bb9c514e1797f819cf67bdfbc14e7e63e8..fdaf0fe6176f082bb20076b2a68bc5f6e2e83b49 100644
Binary files a/out/production/oop-demo4-esimerkit/VirtuaalinenTuote.class and b/out/production/oop-demo4-esimerkit/VirtuaalinenTuote.class differ
diff --git a/out/production/oop-demo4-esimerkit/tuotteet.dat b/out/production/oop-demo4-esimerkit/tuotteet.dat
new file mode 100644
index 0000000000000000000000000000000000000000..a76bcbf70382847194646743ae0312070cc67981
Binary files /dev/null and b/out/production/oop-demo4-esimerkit/tuotteet.dat differ