001package com.hfg.util.io; 002 003import java.io.FilterReader; 004import java.io.IOException; 005import java.io.Reader; 006 007import com.hfg.math.Range; 008 009//------------------------------------------------------------------------------ 010/** 011 FilterReader that provides the specified segment of the stream. 012 <div> 013 @author J. Alex Taylor, hairyfatguy.com 014 </div> 015 */ 016//------------------------------------------------------------------------------ 017// com.hfg Library 018// 019// This library is free software; you can redistribute it and/or 020// modify it under the terms of the GNU Lesser General Public 021// License as published by the Free Software Foundation; either 022// version 2.1 of the License, or (at your option) any later version. 023// 024// This library is distributed in the hope that it will be useful, 025// but WITHOUT ANY WARRANTY; without even the implied warranty of 026// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 027// Lesser General Public License for more details. 028// 029// You should have received a copy of the GNU Lesser General Public 030// License along with this library; if not, write to the Free Software 031// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 032// 033// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 034// jataylor@hairyfatguy.com 035//------------------------------------------------------------------------------ 036 037public class SegmentReader extends FilterReader 038{ 039 private Range<Integer> mSegment; 040 private char[] mBuffer; 041 private int mBufferLimit; 042 private int mBufferIndex; 043 private boolean mEndOfStreamReached; 044 private int mNumBytes; 045 046 //########################################################################### 047 // CONSTRUCTORS 048 //########################################################################### 049 050 //--------------------------------------------------------------------------- 051 public SegmentReader(Reader inReader, Range<Integer> inSegment) 052 { 053 super(inReader); 054 mSegment = inSegment; 055 if (mSegment != null 056 && null == mSegment.getStart()) 057 { 058 mSegment.setStart(1); 059 } 060 } 061 062 //########################################################################### 063 // PUBLIC METHODS 064 //########################################################################### 065 066 //--------------------------------------------------------------------------- 067 @Override 068 public int read(char[] inBuffer, int inOffset, int inMaxReadLength) 069 throws IOException 070 { 071 int theChar; 072 int numCharsRead = 0; 073 do 074 { 075 theChar = read(); 076 if (theChar > 0) 077 { 078 inBuffer[inOffset++] = (char) theChar; 079 numCharsRead++; 080 } 081 } 082 while (theChar >= 0 083 && numCharsRead < inMaxReadLength); 084 085 return (theChar < 0 && 0 == numCharsRead ? -1 : numCharsRead); 086 } 087 088 //--------------------------------------------------------------------------- 089 @Override 090 public int read() 091 throws IOException 092 { 093 if (null == mBuffer) 094 { 095 // Initialize 096 mBuffer = new char[8196]; 097 098 if (mSegment != null 099 && mSegment.getStart() > 1) 100 { 101 super.in.skip(mSegment.getStart() - 1); 102 } 103 } 104 105 if (mBufferIndex >= mBufferLimit) 106 { 107 fillBuffer(); 108 } 109 110 return (mEndOfStreamReached ? -1 : mBuffer[mBufferIndex++]); 111 } 112 113 //########################################################################### 114 // PRIVATE METHODS 115 //########################################################################### 116 117 //--------------------------------------------------------------------------- 118 private void fillBuffer() 119 throws IOException 120 { 121 int fillSize = mBuffer.length; 122 if (mSegment != null 123 && mSegment.getEnd() != null) 124 { 125 int remainingBytesToRead = mSegment.length().intValue() - mNumBytes; 126 fillSize = Math.min(fillSize, remainingBytesToRead); 127 } 128 129 if (fillSize > 0) 130 { 131 mBufferLimit = super.in.read(mBuffer, 0, fillSize); 132 if (mBufferLimit > 0) 133 { 134 mNumBytes += mBufferLimit; 135 } 136 } 137 else 138 { 139 mBufferLimit = -1; 140 } 141 142 if (-1 == mBufferLimit) 143 { 144 mEndOfStreamReached = true; 145 } 146 147 // Reset the index 148 mBufferIndex = 0; 149 } 150}