Mega Code Archive

 
Categories / Java Tutorial / Development
 

Safe UTF

/*   * JBoss, Home of Professional Open Source   * Copyright 2005, JBoss Inc., and individual contributors as indicated   * by the @authors tag. See the copyright.txt in the distribution for a   * full listing of individual contributors.   *   * This is free software; you can redistribute it and/or modify it   * under the terms of the GNU Lesser General Public License as   * published by the Free Software Foundation; either version 2.1 of   * the License, or (at your option) any later version.   *   * This software is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * Lesser General Public License for more details.   *   * You should have received a copy of the GNU Lesser General Public   * License along with this software; if not, write to the Free   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.   */ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /**  *   * A SafeUTF  *   * @author <a href="tim.fox@jboss.com">Tim Fox</a>  * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>  * @version $Revision: 1174 $  *  * $Id: SafeUTF.java 1174 2006-08-02 14:14:32Z timfox $  *   * There is a "bug" in JDK1.4 / 1.5 DataOutputStream.writeUTF()  * which means it does not work with Strings >= 64K serialized size.  * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4806007  *   * We work around this by chunking larger strings into smaller pieces.  *   * Note we only support TextMessage and ObjectMessage bodies with serialized length >= 64K  * We DO NOT support Strings written to BytesMessages or StreamMessages or written as keys or values  * in MapMessages, or as String properties or other String fields having serialized length >= 64K  * This is for performance reasons since there is an overhead in coping with large  * Strings  *   */ public class SafeUTF {          //Default is 16K chunks    private static final int CHUNK_SIZE = 16 * 1024;        private static final byte NULL = 0;        private static final byte NOT_NULL = 1;        public static SafeUTF instance = new SafeUTF(CHUNK_SIZE);        private int chunkSize;        private int lastReadBufferSize;        public int getLastReadBufferSize()    {       return lastReadBufferSize;    }        public SafeUTF(int chunkSize)    {       this.chunkSize = chunkSize;    }           public void safeWriteUTF(DataOutputStream out, String str) throws IOException    {               if (str == null)       {          out.writeByte(NULL);       }       else       {                   int len = str.length();                     short numChunks;                    if (len == 0)          {             numChunks = 0;          }          else          {             numChunks = (short)(((len - 1) / chunkSize) + 1);          }                             out.writeByte(NOT_NULL);                    out.writeShort(numChunks);                         int i = 0;          while (len > 0)          {             int beginCopy = i * chunkSize;                          int endCopy = len <= chunkSize ? beginCopy + len : beginCopy + chunkSize;                   String theChunk = str.substring(beginCopy, endCopy);                             out.writeUTF(theChunk);                          len -= chunkSize;                          i++;          }       }    }        public String safeReadUTF(DataInputStream in) throws IOException    {          boolean isNull = in.readByte() == NULL;              if (isNull)       {          return null;       }              short numChunks = in.readShort();              int bufferSize = chunkSize * numChunks;              // special handling for single chunk       if (numChunks == 1)       {          // The text size is likely to be much smaller than the chunkSize          // so set bufferSize to the min of the input stream available          // and the maximum buffer size. Since the input stream          // available() can be <= 0 we check for that and default to          // a small msg size of 256 bytes.                    int inSize = in.available();                          if (inSize <= 0)          {             inSize = 256;          }          bufferSize = Math.min(inSize, bufferSize);                    lastReadBufferSize = bufferSize;       }                StringBuffer buff = new StringBuffer(bufferSize);                    for (int i = 0; i < numChunks; i++)       {          String s = in.readUTF();          buff.append(s);       }              return buff.toString();    }        }