Java tutorial
/* * Copyright 2006-2013 the original author or authors. * * 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 batch.demo.job; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; import org.springframework.batch.item.file.BufferedReaderFactory; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * A multi-threaded aware {@link FlatFileItemReader} implementation * that starts at the offset specified in bytes relative to the file begin * and reads maxItemCount items/lines from the file. * The offset and number of items to read is passed vie ExecutionContext * parameters set by the {@link FlatFilePartitioner} * <p/> * Reads all the file by default. * * The usage is similar to the {@link FlatFileItemReader}. The <tt>reource</tt>, <tt>maxItemCount</tt>, <tt>startAt</tt> * properties can be set from the <tt>stepExecutionContext</tt> populated by the {@link FlatFilePartitioner}: * <p/> * <pre> * {@code <bean id="partitioner" class="org.springframework.batch.core.partition.support.FlatFilePartitioner" scope="step" * p:resource="#{jobParameters['input.file']}" /> * * <bean id="myReader" class="org.springframework.batch.item.file.MultiThreadedFlatFileItemReader" scope="step"> * ... * <property name="resource" value="#{stepExecutionContext['resource']}"/> * <property name="maxItemCount" value="#{stepExecutionContext['itemsCount']}" /> * <property name="startAt" value="#{stepExecutionContext['startAt']}"/> * </bean> * </pre> * @author Sergey Shcherbakov */ public class MultiThreadedFlatFileItemReader<T> extends FlatFileItemReader<T> { /** * The number of bytes the partition should skip on startup. */ public static final String START_AT_KEY = "start.at"; private long startAt = 0; public MultiThreadedFlatFileItemReader() { setName(ClassUtils.getShortName(MultiThreadedFlatFileItemReader.class)); } /** * Sets the byte offset within the file at which this instance should start reading. Set * to 0 by default so that this instance starts at the first item. * * @param startAt the byte offset at which this instance should * start reading */ public void setStartAt(long startAt) { this.startAt = startAt; } @Override public void open(ExecutionContext executionContext) throws ItemStreamException { if (isSaveState()) { Assert.notNull(executionContext, "ExecutionContext must not be null"); if (executionContext.containsKey(getExecutionContextUserSupport().getKey(START_AT_KEY))) { startAt = executionContext.getLong(getExecutionContextUserSupport().getKey(START_AT_KEY)); } } // replace the DefaultBufferedReaderFactory with an implementation that seeks to the start before reading setBufferedReaderFactory(new BufferedFileReaderFactory(this.startAt)); super.open(executionContext); } @Override public void update(ExecutionContext executionContext) throws ItemStreamException { super.update(executionContext); if (isSaveState()) { executionContext.putLong(getExecutionContextUserSupport().getKey(START_AT_KEY), startAt); } } public static class BufferedFileReaderFactory implements BufferedReaderFactory { private long skipBytes; public BufferedFileReaderFactory() { this(0L); } public BufferedFileReaderFactory(long skipBytes) { this.skipBytes = skipBytes; } /* (non-Javadoc) * @see org.springframework.batch.item.file.BufferedReaderFactory#create(org.springframework.core.io.Resource, java.lang.String) */ public BufferedReader create(Resource resource, String encoding) throws UnsupportedEncodingException, IOException { FileInputStream fis = new FileInputStream(resource.getFile()); fis.skip(this.skipBytes); return new BufferedReader(new InputStreamReader(fis, encoding)); } public void setSkipBytes(long skipBytes) { this.skipBytes = skipBytes; } } }