All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.commons.util.io.CharacterStreamCache Maven / Gradle / Ivy

The newest version!
/*
 * © Copyright IBM Corp. 2012-2013
 * 
 * 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 com.ibm.commons.util.io;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

/**
 * Characters buffer.
 * 

* This class is used to store characters and provides both an Writer for storing the * bytes and an Reader for reading them. It stores the characters in memory in a highly * optimized way, with a possibility of using a backing file when the content is bigger * than a predefined threshold. *

* @ibm-api */ public class CharacterStreamCache { public static final int DEFAULT_BLOCKSIZE = 8192; // Size of a data block public static final int DEFAULT_THRESHOLD = 32; // Number of memory blocks before using a file private int blockSize; private int threshold; private int nBlock; private Block firstBlock; private Block lastBlock; private static class Block { Block next; int count; char[] data; Block(int blockSize) { data = new char[blockSize]; } } /** @ibm-api */ public CharacterStreamCache() { this.blockSize = DEFAULT_BLOCKSIZE; this.threshold = DEFAULT_THRESHOLD; this.nBlock = 1; firstBlock = lastBlock = new Block(blockSize); } /** @ibm-api */ public CharacterStreamCache(int blockSize, int threshold) { this.blockSize = blockSize; this.threshold = threshold; this.nBlock = 1; firstBlock = lastBlock = new Block(blockSize); } /** @ibm-api */ public boolean isEqual(CharacterStreamCache other) { if(blockSize==other.blockSize) { long l1 = getLength(); long l2 = other.getLength(); if(l1==l2) { Block b1 = firstBlock; Block b2 = other.firstBlock; while(b1!=null && b2!=null) { int count = b1.count; for(int i=0; iblockSize ) { b = b.next; pos -= blockSize; } return b.data[pos]; } /** * Clear the data inside the cache. * @ibm-api */ public void clear() { this.nBlock = 1; firstBlock = lastBlock = new Block(blockSize); } /** * Get a reader on the stored data. * @ibm-api */ public Reader getReader() { return new InternalReader(); } /** * Get a writer to store the data. * @ibm-api */ public Writer getWriter() { return new InternalWriter(); } /** * Init the data from an existing reader. * @ibm-api */ public void copyFrom( Reader r ) throws java.io.IOException { // Fill the entire block while(true) { if( lastBlock.count==blockSize ) { addNewBlock(); } int read = r.read(lastBlock.data,lastBlock.count,blockSize-lastBlock.count); if( read<0 ) { return; // The source stream end is reached } lastBlock.count += read; } } /** * Copy the stream to another stream. * @ibm-api */ public void copyTo(Writer w) throws java.io.IOException { for( Block b=firstBlock; b!=null; b=b.next ) { w.write(b.data, 0, b.count); } } /** * Copy the stream to a file. * @ibm-api */ public void copyTo(File f) throws java.io.IOException { Writer w = new BufferedWriter(new FileWriter(f)); try { copyTo(w); } finally { w.close(); } } /** * Convert to a char array. * WARN: this fct is *not* really optimized! * @ibm-api */ public char[] toCharArray() { int length = (int)getLength(); char[] result = new char[length]; int pos = 0; for( Block b=firstBlock; b!=null; b=b.next ) { System.arraycopy( b.data, 0, result, pos, b.count ); pos += b.count; } return result; } public String toString() { return new String(toCharArray()); } /** * Add a new block to the list. */ private final void addNewBlock() { Block b = new Block(blockSize); lastBlock.next = b; lastBlock = b; nBlock++; // TODO: manage the persistence to a temporary file when the threshold is reached! } protected class InternalReader extends Reader { private int currentPosition; private Block currentBlock = firstBlock; public void close() throws java.io.IOException { } public int read() throws IOException { if( currentBlock!=null ) { if( currentPosition>=currentBlock.count ) { if( !nextBlock() || currentBlock.count==0 ) { return -1; } } return (int)currentBlock.data[currentPosition++] & 0xffff; } return -1; } public int read(char b[], int off, int len) throws IOException { if( currentBlock!=null ) { if( currentPosition>=currentBlock.count ) { if( !nextBlock() || currentBlock.count==0 ) { return -1; } } int read = Math.min( len, currentBlock.count-currentPosition ); System.arraycopy( currentBlock.data, currentPosition, b, off, read ); currentPosition += read; return read; } return -1; } private boolean nextBlock() { if( currentBlock!=null ) { currentBlock = currentBlock.next; currentPosition = 0; } return currentBlock!=null; } public long skip(long n) throws IOException { if( currentBlock!=null ) { if( currentPosition>=currentBlock.count ) { if( !nextBlock() ) { return -1; } } int toSkip = Math.min( (int)n, currentBlock.count-currentPosition ); currentPosition += toSkip; return toSkip; } return -1; // EOF } public int available() throws IOException { if( currentBlock!=null ) { if ( currentBlock.count-currentPosition > 0 ){ return currentBlock.count-currentPosition; } //Check the next block return currentBlock.next == null ? 0 : currentBlock.count; } return 0; } } protected class InternalWriter extends Writer { public void write(int b) throws IOException { CharacterStreamCache.this.write(b); } public void write(char b[], int off, int len) throws IOException { CharacterStreamCache.this.write(b,off,len); } public void flush() throws IOException { // Nothing here... } public void close() throws IOException { // Nothing here... } } public final void write(int b) throws IOException { if( lastBlock.count==blockSize ) { addNewBlock(); } lastBlock.data[lastBlock.count++] = (char)b; } public final void write(char b[]) throws IOException { write(b, 0, b.length); } public final void write(char b[], int off, int len) throws IOException { while(len>0 ) { int max = Math.min( len, blockSize-lastBlock.count ); if( max==0 ) { addNewBlock(); max = Math.min( len, blockSize ); } System.arraycopy(b,off,lastBlock.data,lastBlock.count,max); lastBlock.count += max; len-=max; off+=max; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy