📄 coswriter.java
字号:
/**
* Copyright (c) 2003-2006, www.pdfbox.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of pdfbox; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://www.pdfbox.org
*
*/
package org.pdfbox.pdfwriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.pdfbox.cos.COSArray;
import org.pdfbox.cos.COSBase;
import org.pdfbox.cos.COSBoolean;
import org.pdfbox.cos.COSDictionary;
import org.pdfbox.cos.COSDocument;
import org.pdfbox.cos.COSFloat;
import org.pdfbox.cos.COSInteger;
import org.pdfbox.cos.COSName;
import org.pdfbox.cos.COSNull;
import org.pdfbox.cos.COSObject;
import org.pdfbox.cos.COSStream;
import org.pdfbox.cos.COSString;
import org.pdfbox.cos.ICOSVisitor;
import org.pdfbox.exceptions.COSVisitorException;
import org.pdfbox.exceptions.CryptographyException;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdmodel.encryption.SecurityHandler;
import org.pdfbox.persistence.util.COSObjectKey;
/**
* this class acts on a in-memory representation of a pdf document.
*
* todo no support for incremental updates
* todo single xref section only
* todo no linearization
*
* @author Michael Traut
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
* @version $Revision: 1.36 $
*/
public class COSWriter implements ICOSVisitor
{
/**
* The dictionary open token.
*/
public static final byte[] DICT_OPEN = "<<".getBytes();
/**
* The dictionary close token.
*/
public static final byte[] DICT_CLOSE = ">>".getBytes();
/**
* space character.
*/
public static final byte[] SPACE = " ".getBytes();
/**
* The start to a PDF comment.
*/
public static final byte[] COMMENT = "%".getBytes();
/**
* The output version of the PDF.
*/
public static final byte[] VERSION = "PDF-1.4".getBytes();
/**
* Garbage bytes used to create the PDF header.
*/
public static final byte[] GARBAGE = new byte[] {(byte)0xf6, (byte)0xe4, (byte)0xfc, (byte)0xdf};
/**
* The EOF constant.
*/
public static final byte[] EOF = "%%EOF".getBytes();
// pdf tokens
/**
* The reference token.
*/
public static final byte[] REFERENCE = "R".getBytes();
/**
* The XREF token.
*/
public static final byte[] XREF = "xref".getBytes();
/**
* The xref free token.
*/
public static final byte[] XREF_FREE = "f".getBytes();
/**
* The xref used token.
*/
public static final byte[] XREF_USED = "n".getBytes();
/**
* The trailer token.
*/
public static final byte[] TRAILER = "trailer".getBytes();
/**
* The start xref token.
*/
public static final byte[] STARTXREF = "startxref".getBytes();
/**
* The starting object token.
*/
public static final byte[] OBJ = "obj".getBytes();
/**
* The end object token.
*/
public static final byte[] ENDOBJ = "endobj".getBytes();
/**
* The array open token.
*/
public static final byte[] ARRAY_OPEN = "[".getBytes();
/**
* The array close token.
*/
public static final byte[] ARRAY_CLOSE = "]".getBytes();
/**
* The open stream token.
*/
public static final byte[] STREAM = "stream".getBytes();
/**
* The close stream token.
*/
public static final byte[] ENDSTREAM = "endstream".getBytes();
private NumberFormat formatXrefOffset = new DecimalFormat("0000000000");
/**
* The decimal format for the xref object generation number data.
*/
private NumberFormat formatXrefGeneration = new DecimalFormat("00000");
private NumberFormat formatDecimal = NumberFormat.getNumberInstance( Locale.US );
// the stream where we create the pdf output
private OutputStream output;
// the stream used to write standard cos data
private COSStandardOutputStream standardOutput;
// the start position of the x ref section
private long startxref = 0;
// the current object number
private long number = 0;
// maps the object to the keys generated in the writer
// these are used for indirect refrences in other objects
//A hashtable is used on purpose over a hashmap
//so that null entries will not get added.
private Map objectKeys = new Hashtable();
// the list of x ref entries to be made so far
private List xRefEntries = new ArrayList();
//A list of objects to write.
private List objectsToWrite = new ArrayList();
//a list of objects already written
private Set writtenObjects = new HashSet();
//An 'actual' is any COSBase that is not a COSObject.
//need to keep a list of the actuals that are added
//as well as the objects because there is a problem
//when adding a COSObject and then later adding
//the actual for that object, so we will track
//actuals separately.
private Set actualsAdded = new HashSet();
private COSObjectKey currentObjectKey = null;
private PDDocument document = null;
private boolean willEncrypt = false;
/**
* COSWriter constructor comment.
*
* @param os The wrapped output stream.
*/
public COSWriter(OutputStream os)
{
super();
setOutput(os);
setStandardOutput(new COSStandardOutputStream(getOutput()));
formatDecimal.setMaximumFractionDigits( 10 );
formatDecimal.setGroupingUsed( false );
}
/**
* add an entry in the x ref table for later dump.
*
* @param entry The new entry to add.
*/
protected void addXRefEntry(COSWriterXRefEntry entry)
{
getXRefEntries().add(entry);
}
/**
* This will close the stream.
*
* @throws IOException If the underlying stream throws an exception.
*/
public void close() throws IOException
{
if (getStandardOutput() != null)
{
getStandardOutput().close();
}
if (getOutput() != null)
{
getOutput().close();
}
}
/**
* This will get the current object number.
*
* @return The current object number.
*/
protected long getNumber()
{
return number;
}
/**
* This will get all available object keys.
*
* @return A map of all object keys.
*/
public java.util.Map getObjectKeys()
{
return objectKeys;
}
/**
* This will get the output stream.
*
* @return The output stream.
*/
protected java.io.OutputStream getOutput()
{
return output;
}
/**
* This will get the standard output stream.
*
* @return The standard output stream.
*/
protected COSStandardOutputStream getStandardOutput()
{
return standardOutput;
}
/**
* This will get the current start xref.
*
* @return The current start xref.
*/
protected long getStartxref()
{
return startxref;
}
/**
* This will get the xref entries.
*
* @return All available xref entries.
*/
protected java.util.List getXRefEntries()
{
return xRefEntries;
}
/**
* This will set the current object number.
*
* @param newNumber The new object number.
*/
protected void setNumber(long newNumber)
{
number = newNumber;
}
/**
* This will set the output stream.
*
* @param newOutput The new output stream.
*/
private void setOutput( OutputStream newOutput )
{
output = newOutput;
}
/**
* This will set the standard output stream.
*
* @param newStandardOutput The new standard output stream.
*/
private void setStandardOutput(COSStandardOutputStream newStandardOutput)
{
standardOutput = newStandardOutput;
}
/**
* This will set the start xref.
*
* @param newStartxref The new start xref attribute.
*/
protected void setStartxref(long newStartxref)
{
startxref = newStartxref;
}
/**
* This will write the body of the document.
*
* @param doc The document to write the body for.
*
* @throws IOException If there is an error writing the data.
* @throws COSVisitorException If there is an error generating the data.
*/
protected void doWriteBody(COSDocument doc) throws IOException, COSVisitorException
{
COSDictionary trailer = doc.getTrailer();
COSDictionary root = (COSDictionary)trailer.getDictionaryObject( COSName.ROOT );
COSDictionary info = (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Info" ) );
COSDictionary encrypt = (COSDictionary)trailer.getDictionaryObject( COSName.getPDFName( "Encrypt" ) );
if( root != null )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -