Index: trunk/src/com/drew/metadata/iptc/IptcDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcDescriptor.java	(revision 10862)
+++ trunk/src/com/drew/metadata/iptc/IptcDescriptor.java	(revision 13061)
@@ -1,4 +1,4 @@
 /*
- * Copyright 2002-2016 Drew Noakes
+ * Copyright 2002-2017 Drew Noakes
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,4 +35,5 @@
  * @author Drew Noakes https://drewnoakes.com
  */
+@SuppressWarnings("WeakerAccess")
 public class IptcDescriptor extends TagDescriptor<IptcDirectory>
 {
Index: trunk/src/com/drew/metadata/iptc/IptcDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcDirectory.java	(revision 10862)
+++ trunk/src/com/drew/metadata/iptc/IptcDirectory.java	(revision 13061)
@@ -1,4 +1,4 @@
 /*
- * Copyright 2002-2016 Drew Noakes
+ * Copyright 2002-2017 Drew Noakes
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,4 +38,5 @@
  * @author Drew Noakes https://drewnoakes.com
  */
+@SuppressWarnings("WeakerAccess")
 public class IptcDirectory extends Directory
 {
Index: trunk/src/com/drew/metadata/iptc/IptcReader.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcReader.java	(revision 10862)
+++ trunk/src/com/drew/metadata/iptc/IptcReader.java	(revision 13061)
@@ -1,4 +1,4 @@
 /*
- * Copyright 2002-2016 Drew Noakes
+ * Copyright 2002-2017 Drew Noakes
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,6 +29,8 @@
 import com.drew.metadata.Directory;
 import com.drew.metadata.Metadata;
+import com.drew.metadata.StringValue;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.util.Collections;
 
@@ -56,4 +58,5 @@
     public static final int POST_DATA_RECORD = 9;
 */
+    private static final byte IptcMarkerByte = 0x1c;
 
     @NotNull
@@ -67,5 +70,5 @@
         for (byte[] segmentBytes : segments) {
             // Ensure data starts with the IPTC marker byte
-            if (segmentBytes.length != 0 && segmentBytes[0] == 0x1c) {
+            if (segmentBytes.length != 0 && segmentBytes[0] == IptcMarkerByte) {
                 extract(new SequentialByteArrayReader(segmentBytes), metadata, segmentBytes.length);
             }
@@ -107,9 +110,9 @@
             }
 
-            if (startByte != 0x1c) {
+            if (startByte != IptcMarkerByte) {
                 // NOTE have seen images where there was one extra byte at the end, giving
                 // offset==length at this point, which is not worth logging as an error.
                 if (offset != length)
-                    directory.addError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x1c' but got '0x" + Integer.toHexString(startByte) + "'.");
+                    directory.addError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x" + Integer.toHexString(IptcMarkerByte) + "' but got '0x" + Integer.toHexString(startByte) + "'.");
                 return;
             }
@@ -164,16 +167,13 @@
         }
 
-        String string = null;
-
         switch (tagIdentifier) {
             case IptcDirectory.TAG_CODED_CHARACTER_SET:
                 byte[] bytes = reader.getBytes(tagByteCount);
-                String charset = Iso2022Converter.convertISO2022CharsetToJavaCharset(bytes);
-                if (charset == null) {
+                String charsetName = Iso2022Converter.convertISO2022CharsetToJavaCharset(bytes);
+                if (charsetName == null) {
                     // Unable to determine the charset, so fall through and treat tag as a regular string
-                    string = new String(bytes);
-                    break;
+                    charsetName = new String(bytes);
                 }
-                directory.setString(tagIdentifier, charset);
+                directory.setString(tagIdentifier, charsetName);
                 return;
             case IptcDirectory.TAG_ENVELOPE_RECORD_VERSION:
@@ -201,30 +201,36 @@
         // If we haven't returned yet, treat it as a string
         // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value
-        if (string == null) {
-            String encoding = directory.getString(IptcDirectory.TAG_CODED_CHARACTER_SET);
-            if (encoding != null) {
-                string = reader.getString(tagByteCount, encoding);
-            } else {
-                byte[] bytes = reader.getBytes(tagByteCount);
-                encoding = Iso2022Converter.guessEncoding(bytes);
-                string = encoding != null ? new String(bytes, encoding) : new String(bytes);
-            }
+        String charSetName = directory.getString(IptcDirectory.TAG_CODED_CHARACTER_SET);
+        Charset charset = null;
+        try {
+            if (charSetName != null)
+                charset = Charset.forName(charSetName);
+        } catch (Throwable ignored) {
+        }
+
+        StringValue string;
+        if (charSetName != null) {
+            string = reader.getStringValue(tagByteCount, charset);
+        } else {
+            byte[] bytes = reader.getBytes(tagByteCount);
+            Charset charSet = Iso2022Converter.guessCharSet(bytes);
+            string = charSet != null ? new StringValue(bytes, charSet) : new StringValue(bytes, null);
         }
 
         if (directory.containsTag(tagIdentifier)) {
-            // this fancy string[] business avoids using an ArrayList for performance reasons
-            String[] oldStrings = directory.getStringArray(tagIdentifier);
-            String[] newStrings;
+            // this fancy StringValue[] business avoids using an ArrayList for performance reasons
+            StringValue[] oldStrings = directory.getStringValueArray(tagIdentifier);
+            StringValue[] newStrings;
             if (oldStrings == null) {
                 // TODO hitting this block means any prior value(s) are discarded
-                newStrings = new String[1];
+                newStrings = new StringValue[1];
             } else {
-                newStrings = new String[oldStrings.length + 1];
+                newStrings = new StringValue[oldStrings.length + 1];
                 System.arraycopy(oldStrings, 0, newStrings, 0, oldStrings.length);
             }
             newStrings[newStrings.length - 1] = string;
-            directory.setStringArray(tagIdentifier, newStrings);
+            directory.setStringValueArray(tagIdentifier, newStrings);
         } else {
-            directory.setString(tagIdentifier, string);
+            directory.setStringValue(tagIdentifier, string);
         }
     }
Index: trunk/src/com/drew/metadata/iptc/Iso2022Converter.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/Iso2022Converter.java	(revision 10862)
+++ trunk/src/com/drew/metadata/iptc/Iso2022Converter.java	(revision 13061)
@@ -1,4 +1,4 @@
 /*
- * Copyright 2002-2016 Drew Noakes
+ * Copyright 2002-2017 Drew Noakes
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,7 +59,7 @@
 
     /**
-     * Attempts to guess the encoding of a string provided as a byte array.
+     * Attempts to guess the {@link Charset} of a string provided as a byte array.
      * <p>
-     * Encodings trialled are, in order:
+     * Charsets trialled are, in order:
      * <ul>
      *     <li>UTF-8</li>
@@ -68,5 +68,5 @@
      * </ul>
      * <p>
-     * Its only purpose is to guess the encoding if and only if iptc tag coded character set is not set. If the
+     * Its only purpose is to guess the Charset if and only if IPTC tag coded character set is not set. If the
      * encoding is not UTF-8, the tag should be set. Otherwise it is bad practice. This method tries to
      * workaround this issue since some metadata manipulating tools do not prevent such bad practice.
@@ -79,5 +79,5 @@
      */
     @Nullable
-    static String guessEncoding(@NotNull final byte[] bytes)
+    static Charset guessCharSet(@NotNull final byte[] bytes)
     {
         String[] encodings = { UTF_8, System.getProperty("file.encoding"), ISO_8859_1 };
@@ -85,9 +85,10 @@
         for (String encoding : encodings)
         {
-            CharsetDecoder cs = Charset.forName(encoding).newDecoder();
+            Charset charset = Charset.forName(encoding);
+            CharsetDecoder cs = charset.newDecoder();
 
             try {
                 cs.decode(ByteBuffer.wrap(bytes));
-                return encoding;
+                return charset;
             } catch (CharacterCodingException e) {
                 // fall through...
Index: trunk/src/com/drew/metadata/iptc/package-info.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/package-info.java	(revision 13061)
+++ trunk/src/com/drew/metadata/iptc/package-info.java	(revision 13061)
@@ -0,0 +1,4 @@
+/**
+ * Contains classes for the extraction and modelling of IPTC metadata.
+ */
+package com.drew.metadata.iptc;
Index: trunk/src/com/drew/metadata/iptc/package.html
===================================================================
--- trunk/src/com/drew/metadata/iptc/package.html	(revision 10862)
+++ 	(revision )
@@ -1,33 +1,0 @@
-<!--
-  ~ Copyright 2002-2016 Drew Noakes
-  ~
-  ~    Licensed under the Apache License, Version 2.0 (the "License");
-  ~    you may not use this file except in compliance with the License.
-  ~    You may obtain a copy of the License at
-  ~
-  ~        http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~    Unless required by applicable law or agreed to in writing, software
-  ~    distributed under the License is distributed on an "AS IS" BASIS,
-  ~    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~    See the License for the specific language governing permissions and
-  ~    limitations under the License.
-  ~
-  ~ More information about this project is available at:
-  ~
-  ~    https://drewnoakes.com/code/exif/
-  ~    https://github.com/drewnoakes/metadata-extractor
-  -->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-</head>
-<body bgcolor="white">
-
-Contains classes for the extraction and modelling of IPTC metadata.
-
-<!-- Put @see and @since tags down here. -->
-
-</body>
-</html>
