Merge branch 'dev'
diff --git a/build.gradle b/build.gradle
index 050b85b..c076045 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,7 +8,7 @@
 
 description = 'MDF Sorter'
 group = 'org.eclipse.mdm'
-version = '1.0.2'
+version = '1.0.3'
 
 apply plugin: 'java'
 apply plugin: 'eclipse'
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/MDFParser.java b/src/main/java/org/eclipse/mdm/mdfsorter/MDFParser.java
index 24f6450..999d61f 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/MDFParser.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/MDFParser.java
@@ -58,6 +58,13 @@
 			MDFSorter.log.severe("MDF Version " + String.valueOf(versionnum) + "is not supported. Aborting.");
 			throw new IllegalArgumentException("Unsupported MDF Version.");
 		} else if (version < 400) {
+			if (version == 330) {
+				int codePage = MDF4Util.readUInt16(getDataBuffer(idblock, 30, 32));
+				if (codePage != 0) {
+					MDFSorter.log.warning("code page is defined to be '" + codePage
+							+ "' (value is ignored and ISO-8859-1 is used for string en-/decoding)");
+				}
+			}
 			boolean bigendian = MDF4Util.readUInt16(getDataBuffer(idblock, 24, 26)) != 0;
 			myParser = new MDF3Parser(in, bigendian);
 		} else {
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/MDFSorter.java b/src/main/java/org/eclipse/mdm/mdfsorter/MDFSorter.java
index 3e64cd5..66a228a 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/MDFSorter.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/MDFSorter.java
@@ -36,7 +36,7 @@
 	/**
 	 * Version of this tool as String. (Used in the file Header)
 	 */
-	public static final String VERSIONSTRING = "1.0.2";
+	public static final String VERSIONSTRING = "1.0.3";
 
 	/**
 	 * The logger for this application
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CCBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CCBLOCK.java
index 46ad31e..f158a65 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CCBLOCK.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CCBLOCK.java
@@ -215,7 +215,7 @@
 		setMaxPhysValue(MDF4Util.readReal(MDFParser.getDataBuffer(content, 10, 18)));
 
 		// CHAR 20 Physical unit
-		setPhysUnit(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 18, 38), 20));
+		setPhysUnit(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 18, 38), 20));
 
 		// UINT16 1 Conversion formula identifier
 		// 0 = parametric, linear
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CNBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CNBLOCK.java
index a94c633..a04bbb0 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CNBLOCK.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/CNBLOCK.java
@@ -260,10 +260,10 @@
 
 		// CHAR 32 Signal name, i.e. the first 32 characters of the ASAM-MCD
 		// unique name
-		setSignalName(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 2, 34), 32));
+		setSignalName(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 2, 34), 32));
 
 		// CHAR 128 Signal description
-		setSignalDescription(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 34, 162), 128));
+		setSignalDescription(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 34, 162), 128));
 
 		// UINT16 1 Number of the first bits [0..n] (bit position within a byte:
 		// bit 0 is the least significant
@@ -315,9 +315,9 @@
 
 		b.put(MDF3Util.getBytesUInt16(getChannelType(), isBigEndian()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getSignalName()));
+		b.put(MDF3Util.getBytesCharsISO8859(getSignalName()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getSignalDescription()));
+		b.put(MDF3Util.getBytesCharsISO8859(getSignalDescription()));
 
 		b.put(MDF3Util.getBytesUInt16(getNumberOfFirstBits(), isBigEndian()));
 
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/HDBLOCK.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/HDBLOCK.java
index af94ee5..66896d0 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/HDBLOCK.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/HDBLOCK.java
@@ -12,7 +12,6 @@
 import java.nio.ByteBuffer;
 
 import org.eclipse.mdm.mdfsorter.MDFParser;
-import org.eclipse.mdm.mdfsorter.mdf4.MDF4Util;
 
 /**
  * The Data Group Block
@@ -199,16 +198,16 @@
 		setNumberOfDataGroups(MDF3Util.readUInt16(MDFParser.getDataBuffer(content, 0, 2), isBigEndian()));
 
 		// CHAR 10 Date when the recording was started
-		setDateStarted(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 2, 12), 10));
+		setDateStarted(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 2, 12), 10));
 
 		// CHAR 8 Signal name, i.e. the first 32 characters of the ASAM-MCD
 		// unique name
-		setTimeStarted(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 12, 20), 8));
+		setTimeStarted(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 12, 20), 8));
 
-		setAuthor(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 20, 52), 32));
-		setDepartment(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 52, 84), 32));
-		setProjectName(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 84, 116), 32));
-		setMeaObject(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 116, 148), 32));
+		setAuthor(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 20, 52), 32));
+		setDepartment(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 52, 84), 32));
+		setProjectName(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 84, 116), 32));
+		setMeaObject(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 116, 148), 32));
 
 		if (content.length > 148) {
 			// UNINT 64 Timestamp
@@ -225,7 +224,7 @@
 		}
 
 		if (content.length > 160) {
-			setTimerIdent(MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(content, 160, 192), 32));
+			setTimerIdent(MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(content, 160, 192), 32));
 		}
 
 	}
@@ -238,17 +237,17 @@
 
 		b.put(MDF3Util.getBytesUInt16(getNumberOfDataGroups(), isBigEndian()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getDateStarted()));
+		b.put(MDF3Util.getBytesCharsISO8859(getDateStarted()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getTimeStarted()));
+		b.put(MDF3Util.getBytesCharsISO8859(getTimeStarted()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getAuthor()));
+		b.put(MDF3Util.getBytesCharsISO8859(getAuthor()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getDepartment()));
+		b.put(MDF3Util.getBytesCharsISO8859(getDepartment()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getProjectName()));
+		b.put(MDF3Util.getBytesCharsISO8859(getProjectName()));
 
-		b.put(MDF4Util.getBytesCharsUTF8(getMeaObject()));
+		b.put(MDF3Util.getBytesCharsISO8859(getMeaObject()));
 
 		if (arraylength > 148) {
 			b.put(MDF3Util.getBytesUInt64(getTimestamp(), isBigEndian()));
@@ -263,7 +262,7 @@
 		}
 
 		if (arraylength > 160) {
-			b.put(MDF4Util.getBytesCharsUTF8(getTimerIdent()));
+			b.put(MDF3Util.getBytesCharsISO8859(getTimerIdent()));
 		}
 
 		return b.array();
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Parser.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Parser.java
index e9a5c16..0381b62 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Parser.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Parser.java
@@ -120,7 +120,7 @@
 		in.position(start.getPos());
 		byte[] head = readBytes(4, in);
 		// Read header of this block
-		String blktyp = MDF4Util.readCharsUTF8(MDFParser.getDataBuffer(head, 0, 2), 2);
+		String blktyp = MDF3Util.readCharsISO8859(MDFParser.getDataBuffer(head, 0, 2), 2);
 		start.setId(blktyp);
 		int blklength = MDF4Util.readUInt16(MDFParser.getDataBuffer(head, 2, 4));
 		start.setLength(blklength);
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3ProcessWriter.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3ProcessWriter.java
index 19baab9..80f48f5 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3ProcessWriter.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3ProcessWriter.java
@@ -13,6 +13,7 @@
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -40,6 +41,8 @@
  */
 public class MDF3ProcessWriter extends MDFAbstractProcessWriter<MDF3GenBlock> {
 
+	private MDF3GenBlock lastDGBlockParent;
+
 	/**
 	 * Main Constructor.
 	 *
@@ -74,6 +77,8 @@
 		for (MDF3GenBlock blk : filestructure.getList()) {
 			if (blk instanceof CGBLOCK) {
 				numberOfDatagroups++;
+			} else if(blk instanceof HDBLOCK) {
+				lastDGBlockParent = blk;
 			}
 		}
 		// Check if zip flag is not set
@@ -237,27 +242,46 @@
 
 		long[][] startaddresses = fillRecordArray(recCounters, recNumtoArrIdx, recNumtoSize, prov, redundantids);
 
-		MDF3GenBlock last = (MDF3GenBlock) prob.getParentnode();
-
 		// write new blocks
 		for (CGBLOCK cgroup : groups) {
 			int arridx = recNumtoArrIdx.get(cgroup.getRecordId());
 			MDFSorter.log.fine("Writing data for Block " + arridx + ".");
 			long newlength;
+
+			long newCycleCount = newCycleCount(startaddresses[arridx]);
+			if (newCycleCount > -1) {
+				// missing records exist, update cycle count
+				// to match number of existing records
+				cgroup.setCycleCount(newCycleCount);
+			}
+
 			// create new datagroup
-			last = copyChannelInfrastructure(last, cgroup);
+			lastDGBlockParent = copyChannelInfrastructure(lastDGBlockParent, cgroup);
 			long reclen = cgroup.getDataBytes();
 			newlength = cgroup.getCycleCount() * cgroup.getDataBytes();
-			MDF3BlocksSplittMerger splitmerger = new MDF3BlocksSplittMerger(this, last, newlength, prov);
+			MDF3BlocksSplittMerger splitmerger = new MDF3BlocksSplittMerger(this, lastDGBlockParent, newlength, prov);
 
 			// write data sections.
 			for (long l : startaddresses[arridx]) {
+				if (l == -1L) {
+					// remaining records are missing => trim
+					break;
+				}
 				splitmerger.splitmerge(l + idSize, reclen);
 			}
 			splitmerger.setLinks();
 		}
 	}
 
+	private long newCycleCount(long[] addrs) {
+		for (int i = 0; i < addrs.length; i++) {
+			if (addrs[i] == -1L) {
+				return i;
+			}
+		}
+		return -1L;
+	}
+
 	public long[][] fillRecordArray(long[] recordCounters, Map<Integer, Integer> recNumtoArrIdx,
 			Map<Integer, Integer> recNumtoSize, AbstractDataProvider prov, boolean redundantids)
 			throws IOException, DataFormatException {
@@ -273,6 +297,7 @@
 		for (long i : recordCounters) {
 			totalRecords += i;
 			startaddresses[counter++] = new long[(int) i];
+			Arrays.fill(startaddresses[counter - 1], -1L);
 		}
 
 		int[] foundrecCounters = new int[recordCounters.length];
@@ -287,7 +312,12 @@
 			int foundID = MDF3Util.readUInt8(databuf);
 			Integer foundsize = recNumtoSize.get(foundID);
 			if (foundsize == null) { // Check if a size was found.
-				throw new RuntimeException("No Size known for record ID " + foundID + ".");
+				if (foundID == 0) {
+					MDFSorter.log.info("Record ID '0' found => cutting off missing records,"
+							+ " since those are not recoverable.");
+					return startaddresses;
+				}
+				throw new RuntimeException("Record ID '" + foundID + "' does not exist, file may be corrupt.");
 			}
 			if (redundantids) {
 				// do a sanity check with the second id
diff --git a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Util.java b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Util.java
index 8f597a4..2ef61f2 100644
--- a/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Util.java
+++ b/src/main/java/org/eclipse/mdm/mdfsorter/mdf3/MDF3Util.java
@@ -8,6 +8,7 @@
 
 package org.eclipse.mdm.mdfsorter.mdf3;
 
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
@@ -225,4 +226,26 @@
 	public static byte[] getBytesLink(long val, boolean bigendian) {
 		return getBytesUInt32(val, bigendian);
 	}
+
+	/**
+	 * Read a String from ISO8859 encoded bytes
+	 *
+	 * @param bb
+	 *            The ByteBuffer to use.
+	 * @param length
+	 *            Number of chars to read.
+	 * @return The result as String.
+	 * @throws IOException
+	 *             If an reading error occurs.
+	 */
+	public static String readCharsISO8859(ByteBuffer bb, int length) throws IOException {
+		byte[] b = new byte[length];
+		bb.get(b);
+		return new String(b, 0, length, "ISO-8859-1");
+	}
+
+	public static byte[] getBytesCharsISO8859(String s) throws IOException {
+		return s.getBytes("ISO-8859-1");
+	}
+
 }