⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sstdeserializer.java

📁 java 报表 to office文档: 本包由java语言开发
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* ====================================================================   Copyright 2002-2004   Apache Software Foundation   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.==================================================================== */        package org.apache.poi.hssf.record;import org.apache.poi.util.BinaryTree;import org.apache.poi.util.LittleEndian;import org.apache.poi.util.LittleEndianConsts;/** * Handles the task of deserializing a SST string.  The two main entry points are * * @author Glen Stampoultzis (glens at apache.org) * @author Jason Height (jheight at apache.org) */class SSTDeserializer{    private BinaryTree strings;    /** this is the number of characters that have been read prior to the continuation */    private int continuationReadChars;    /** this is the string we were working on before hitting the end of the current record. This string is NOT finished. */    private String unfinishedString;    /** this is true if the string uses wide characters */    private boolean wideChar;    /** this is true if the string is a rich text string */    private boolean richText;    /** this is true if the string is a far east string or some other wierd string */    private boolean extendedText;    /** Number of formatting runs in this rich text field */    private short runCount;    /** Number of characters in current string */    private int charCount;    private int extensionLength;    private int continueSkipBytes = 0;    public SSTDeserializer( BinaryTree strings )    {        this.strings = strings;        initVars();    }    private void initVars()    {        runCount = 0;        continuationReadChars = 0;        unfinishedString = "";//        bytesInCurrentSegment = 0;//        stringDataOffset = 0;        wideChar = false;        richText = false;        extendedText = false;        continueSkipBytes = 0;    }    /**     * This is the starting point where strings are constructed.  Note that     * strings may span across multiple continuations. Read the SST record     * carefully before beginning to hack.     */    public void manufactureStrings( final byte[] data, final int initialOffset)    {        initVars();        int offset = initialOffset;        final int dataSize = data.length;        while ( offset < dataSize )        {            int remaining = dataSize - offset;            if ( ( remaining > 0 ) && ( remaining < LittleEndianConsts.SHORT_SIZE ) )            {                throw new RecordFormatException( "Cannot get length of the last string in SSTRecord" );            }            if ( remaining == LittleEndianConsts.SHORT_SIZE )            {              //JMH Dont know about this                setContinuationCharsRead( 0 );//LittleEndian.getUShort( data, offset ) );                unfinishedString = "";                break;            }            charCount = LittleEndian.getUShort( data, offset );            int charsRead = charCount;            readStringHeader( data, offset );            boolean stringContinuesOverContinuation = remaining < totalStringSize();            if ( stringContinuesOverContinuation )            {                int remainingBytes = dataSize - offset - stringHeaderOverhead();                //Only read the size of the string or whatever is left before the                //continuation                charsRead = Math.min(charsRead, calculateCharCount( remainingBytes ));                setContinuationCharsRead( charsRead );                                if (charsRead == charCount) {                  //Since all of the characters will have been read, but the entire string (including formatting runs etc)                  //hasnt, Compute the number of bytes to skip when the continue record starts                  continueSkipBytes = offsetForContinuedRecord(0) - (remainingBytes - calculateByteCount(charsRead));                }            }            processString( data, offset, charsRead );            offset += totalStringSize();            if ( stringContinuesOverContinuation )            {                break;            }        }    }//    private void dump( final byte[] data, int offset, int length )//    {//        try//        {//            System.out.println( "------------------- SST DUMP -------------------------" );//            HexDump.dump( (byte[]) data, offset, System.out, offset, length );//        }//        catch ( IOException e )//        {//        }//        catch ( ArrayIndexOutOfBoundsException e )//        {//        }//        catch ( IllegalArgumentException e )//        {//        }//    }    /**     * Detemines the option types for the string (ie, compressed or uncompressed unicode, rich text string or     * plain string etc) and calculates the length and offset for the string.     *     */    private void readStringHeader( final byte[] data, final int index )    {        byte optionFlag = data[index + LittleEndianConsts.SHORT_SIZE];        wideChar = ( optionFlag & 1 ) == 1;        extendedText = ( optionFlag & 4 ) == 4;        richText = ( optionFlag & 8 ) == 8;        runCount = 0;        if ( richText )        {            runCount = LittleEndian.getShort( data, index + SSTRecord.STRING_MINIMAL_OVERHEAD );        }        extensionLength = 0;        if ( extendedText )        {            extensionLength = LittleEndian.getInt( data, index + SSTRecord.STRING_MINIMAL_OVERHEAD                    + (richText ? LittleEndianConsts.SHORT_SIZE : 0) );        }    }    /**     * Reads a string or the first part of a string.     *     * @param characters the number of characters to write.     *     * @return the number of bytes written.     */    private int processString( final byte[] data, final int dataIndex, final int characters )    {        // length is the length we store it as.  not the length that is read.        int length = SSTRecord.STRING_MINIMAL_OVERHEAD + calculateByteCount( characters );        byte[] unicodeStringBuffer = new byte[length];        int offset = 0;        // Set the length in characters        LittleEndian.putUShort( unicodeStringBuffer, offset, characters );        offset += LittleEndianConsts.SHORT_SIZE;        // Set the option flags        unicodeStringBuffer[offset] = data[dataIndex + offset];        // Copy in the string data        int bytesRead = unicodeStringBuffer.length - SSTRecord.STRING_MINIMAL_OVERHEAD;        arraycopy( data, dataIndex + stringHeaderOverhead(), unicodeStringBuffer, SSTRecord.STRING_MINIMAL_OVERHEAD, bytesRead );        // Create the unicode string        UnicodeString string = new UnicodeString( UnicodeString.sid,                (short) unicodeStringBuffer.length,                unicodeStringBuffer );        setContinuationCharsRead( calculateCharCount(bytesRead));        if ( isStringFinished() )        {            Integer integer = new Integer( strings.size() );            addToStringTable( strings, integer, string );        }        else        {            unfinishedString = string.getString();        }        return bytesRead;    }    private boolean isStringFinished()    {        return getContinuationCharsRead() == charCount;    }    /**     * Okay, we are doing some major cheating here. Because we can't handle rich text strings properly     * we end up getting duplicate strings.  To get around this I'm doing two things: 1. Converting rich     * text to normal text and 2. If there's a duplicate I'm adding a space onto the end.  Sneaky perhaps     * but it gets the job done until we can handle this a little better.     */    static public void addToStringTable( BinaryTree strings, Integer integer, UnicodeString string )    {        if ( string.isRichText() )            string.setOptionFlags( (byte) ( string.getOptionFlags() & ( ~8 ) ) );        if ( string.isExtendedText() )            string.setOptionFlags( (byte) ( string.getOptionFlags() & ( ~4 ) ) );        boolean added = false;        while ( added == false )        {            try            {                strings.put( integer, string );                added = true;            }            catch ( Exception ignore )            {                string.setString( string.getString() + " " );            }        }    }    private int calculateCharCount( final int byte_count )    {        return byte_count / ( wideChar ? LittleEndianConsts.SHORT_SIZE : LittleEndianConsts.BYTE_SIZE );    }    /**     * Process a Continue record. A Continue record for an SST record     * contains the same kind of data that the SST record contains,     * with the following exceptions:     * <P>     * <OL>     * <LI>The string counts at the beginning of the SST record are     *     not in the Continue record     * <LI>The first string in the Continue record might NOT begin     *     with a size. If the last string in the previous record is     *     continued in this record, the size is determined by that     *     last string in the previous record; the first string will     *     begin with a flag byte, followed by the remaining bytes (or     *     words) of the last string from the previous     *     record. Otherwise, the first string in the record will     *     begin with a string length     * </OL>     *     * @param record the Continue record's byte data     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -