PDF Java Toolkit: Writing Your Own Filesystem

PDF Java Toolkit: Writing Your Own Filesystem

The PDF Java Toolkit (PDFJT) comes with utility code in its samples for making a random-access byte reader and writer suitable for use with PDFJT for opening PDF files and for saving PDF files. This utility code instantiates a ByteReader / ByteWriter as defined in PDFJT. For those who wish to implement their own filesystem reader or writer, here we present an example of doing so. While we’ll include this example in PDFJT soon, I figured you might want a preview.

In PDFJT PDF documents are opened and saved via classes that implement the com.adobe.internal.io.ByteWriter interface (as well as ByteReader; ByteWriter extends ByteReader and so a ByteWriter can be used in either case). The ByteReader and ByteWriter interfaces are not in the API documentation but are fairly simple. It’s probably easier to show a complete, albeit simple, implementation:

PDFJTSampleByteWriter.java

[sourcecode language=”java”]
package com.adobe.pdfjt.samples;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;

import com.adobe.internal.io.ByteReader;
import com.adobe.internal.io.ByteWriter;
import com.adobe.internal.io.RandomAccessFileByteReader;
import com.adobe.internal.io.RandomAccessFileByteWriter;

public final class PDFJTSampleByteWriter
implements ByteWriter
{
private boolean closed = false;
private RandomAccessFile file;

public PDFJTSampleByteWriter(RandomAccessFile file, int numberOfBuffers, int bufferSize)
{
this.file = file;
}

public PDFJTSampleByteWriter(RandomAccessFile file)
{
this.file = file;
}

public void write(long position, int b) throws IOException
{
byte[] writeIntBuf = new byte[1];
writeIntBuf[0] = (byte)(b & 0xFF);
this.write(position, writeIntBuf, 0, 1);
}

public void write(long position, byte[] b, int offset, int length)
throws IOException
{
if (this.closed)
{
throw new IOException("ByteReader was closed");
}

this.file.seek(position);
this.file.write(b, offset, length);
}

public long length() throws IOException
{
if (this.closed)
{
throw new IOException("ByteReader was closed");
}
return this.file.length();
}

// No implementation for this as a RandomAccessFile – based class.
// If you were to change this implementation to cache, or buffer, or
// otherwise be more sophisticated, then your flush() method would probably
// have something to do.
public void flush() throws IOException
{
if (this.closed)
{
throw new IOException("ByteReader was closed");
}
}

public void close() throws IOException
{
if (this.closed)
{
return;
}
this.closed = true;
this.file.close();
}

public int read(long position) throws IOException
{
if (this.closed)
{
throw new IOException("ByteReader was closed");
}

byte[] readIntBuf = new byte[1];
if (1 != this.read(position, readIntBuf, 0, 1))
{
throw new IOException("ByteReader could not read 1 int");
}
return (int)(readIntBuf[0] & 0xFF);
}

public int read(long position, byte[] b, int offset, int length)
throws IOException
{
if (this.closed)
{
throw new IOException("ByteReader was closed");
}

this.file.seek(position);
return this.file.read(b, offset, length);
}

public String toString()
{
return this.file.toString();
}
}
[/sourcecode]

Using this PDFJTSampleByteWriter is straightforward: instead of calling the getRAFByteReader() and getRAFByteWriter() methods from the sample utility code, instantiate the ByteWriter you created with a RandomAccessFile:

[sourcecode language=”java”]
RandomAccessFile inputRAF = SampleFileServices.getRandomAccessFile(args[0]);
ByteReader sourceFile = new PDFJTSampleByteWriter(inputRAF);
[/sourcecode]

This resulting ByteWriter can then be used to open a PDF document as is currently implemented in the PDFJT samples, or can be used to save a PDF document in like manner.

Leave a Reply

Your email address will not be published. Required fields are marked *