使用 Spring 或 Java 解析固定格式的平面文件 8
Parsing a fixed format flat file using Spring or Java 8
所以我有这个平面文件,我需要对其进行解析以获取其中的各个字段。例如位置 0 到 2 是一个 header 文字,位置 3 到 10 是名称等等。
我很难弄清楚如何去做这件事。 Spring 批处理中有什么可以用来解析这个固定长度的文件吗?
示例平面文件如下:
H10000001140658760000 16778816471A 422
I10000001140658760IT2016060310850028010700030719564-010 L00000072
所以在上面的格式中,
H1
是行文字,0000001140658760
是收据编号,
LMS
是供应商代码等等。
我需要将这些映射到各个字段,例如
- 位置0到位置2是文字,
- 位置3到位置18为收据编号,
- 第18位到第28位为供应商代码
请指教
所以我尝试将 BeanIO 与 Spring 批处理集成一起使用,但在尝试创建 reader.
时出现错误
我收到 org.springframework.batch.item.ItemStreamException:未能初始化 reader。
下面是我的代码:
public BeanIOFlatFileItemReader<String> createBeanIOFlatFileItemReader(File file) throws Exception {
BeanIOFlatFileItemReader<String> reader = new BeanIOFlatFileItemReader<>();
reader.setStreamFactory(StreamFactory.newInstance());
reader.setResource(new FileSystemResource(file));
reader.setStreamMapping(new ClassPathResource("mapping.xml"));
reader.setStreamName("file");//this name shud be same as the name of the stream in the mapping.xml
reader.afterPropertiesSet();// Adding this solved the issue!
reader.open(new ExecutionContext());
return reader;
}
下面是我正在使用的映射文件:
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="file" format="fixedlength" minOccurs="0" maxOccurs="unbounded">
<record name="employee" class="Employee" order="1">
</record>
<record name="company" class="Company" order="2">
</record>
</stream>
</beanio>
这是堆栈跟踪:
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:147)
at com.gateway.fileloader.fileprocessor.ArchiveFileProcessor.createBeanIOFlatFileItemReader(ArchiveFileProcessor.java:211)
at com.gateway.fileloader.fileprocessor.ArchiveFileProcessor.doProcess(ArchiveFileProcessor.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:113)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:129)
at org.springframework.expression.spel.ast.MethodReference.access[=15=]0(MethodReference.java:49)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:347)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:131)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:330)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:166)
at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:317)
at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:155)
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:93)
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:89)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.handleMessage(SourcePollingChannelAdapter.java:161)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:251)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access[=15=]0(AbstractPollingEndpoint.java:57)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:176)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:173)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:330)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.run(ErrorHandlingTaskExecutor.java:55)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:324)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: No stream mapping configured for name 'fileDummy'
at org.beanio.internal.DefaultStreamFactory.getStream(DefaultStreamFactory.java:129)
at org.beanio.internal.DefaultStreamFactory.createReader(DefaultStreamFactory.java:70)
at org.beanio.spring.BeanIOFlatFileItemReader.doOpen(BeanIOFlatFileItemReader.java:129)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144)
... 48 more
你可以通过 org.beanio.spring.BeanIOFlatFileItemReader
批量-context.xml
<bean id="fixedWidthFileReader" class="org.beanio.spring.BeanIOFlatFileItemReader" scope="step">
<property name="streamMapping" value="classpath:META-INF/mapping.xml"/>
<property name="streamName" value="flatFileStream" />
<property name="resource" value="resource/inputFile"/></bean>
mapping.xml
<stream name="flatFileStream" format="fixedlength">
<record name="flatFileContents" class="com.test.YourPojo" order="1">
<field name="header" length="2" />
<field name="name" length="15" />
<field name="supplierCode" length="10" />
</record>
com.test.YourPojo 是域模型。
注意:mapping.xml 中的长度将根据您的要求而有所不同。
Spring Batch 为这个用例提供了 FixedLengthTokenizer
。您可以在此处的文档中阅读更多相关信息:http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/file/transform/FixedLengthTokenizer.html
所以我有这个平面文件,我需要对其进行解析以获取其中的各个字段。例如位置 0 到 2 是一个 header 文字,位置 3 到 10 是名称等等。 我很难弄清楚如何去做这件事。 Spring 批处理中有什么可以用来解析这个固定长度的文件吗? 示例平面文件如下:
H10000001140658760000 16778816471A 422
I10000001140658760IT2016060310850028010700030719564-010 L00000072
所以在上面的格式中,
H1
是行文字,0000001140658760
是收据编号,
LMS
是供应商代码等等。
我需要将这些映射到各个字段,例如
- 位置0到位置2是文字,
- 位置3到位置18为收据编号,
- 第18位到第28位为供应商代码
请指教
所以我尝试将 BeanIO 与 Spring 批处理集成一起使用,但在尝试创建 reader.
时出现错误
我收到 org.springframework.batch.item.ItemStreamException:未能初始化 reader。
下面是我的代码:
public BeanIOFlatFileItemReader<String> createBeanIOFlatFileItemReader(File file) throws Exception {
BeanIOFlatFileItemReader<String> reader = new BeanIOFlatFileItemReader<>();
reader.setStreamFactory(StreamFactory.newInstance());
reader.setResource(new FileSystemResource(file));
reader.setStreamMapping(new ClassPathResource("mapping.xml"));
reader.setStreamName("file");//this name shud be same as the name of the stream in the mapping.xml
reader.afterPropertiesSet();// Adding this solved the issue!
reader.open(new ExecutionContext());
return reader;
}
下面是我正在使用的映射文件:
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="file" format="fixedlength" minOccurs="0" maxOccurs="unbounded">
<record name="employee" class="Employee" order="1">
</record>
<record name="company" class="Company" order="2">
</record>
</stream>
</beanio>
这是堆栈跟踪:
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:147)
at com.gateway.fileloader.fileprocessor.ArchiveFileProcessor.createBeanIOFlatFileItemReader(ArchiveFileProcessor.java:211)
at com.gateway.fileloader.fileprocessor.ArchiveFileProcessor.doProcess(ArchiveFileProcessor.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:113)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:129)
at org.springframework.expression.spel.ast.MethodReference.access[=15=]0(MethodReference.java:49)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:347)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:131)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:330)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:166)
at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:317)
at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:155)
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:93)
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:89)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:392)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.handleMessage(SourcePollingChannelAdapter.java:161)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:251)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access[=15=]0(AbstractPollingEndpoint.java:57)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:176)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.call(AbstractPollingEndpoint.java:173)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:330)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.run(ErrorHandlingTaskExecutor.java:55)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:324)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: No stream mapping configured for name 'fileDummy'
at org.beanio.internal.DefaultStreamFactory.getStream(DefaultStreamFactory.java:129)
at org.beanio.internal.DefaultStreamFactory.createReader(DefaultStreamFactory.java:70)
at org.beanio.spring.BeanIOFlatFileItemReader.doOpen(BeanIOFlatFileItemReader.java:129)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144)
... 48 more
你可以通过 org.beanio.spring.BeanIOFlatFileItemReader
批量-context.xml
<bean id="fixedWidthFileReader" class="org.beanio.spring.BeanIOFlatFileItemReader" scope="step">
<property name="streamMapping" value="classpath:META-INF/mapping.xml"/>
<property name="streamName" value="flatFileStream" />
<property name="resource" value="resource/inputFile"/></bean>
mapping.xml
<stream name="flatFileStream" format="fixedlength">
<record name="flatFileContents" class="com.test.YourPojo" order="1">
<field name="header" length="2" />
<field name="name" length="15" />
<field name="supplierCode" length="10" />
</record>
com.test.YourPojo 是域模型。
注意:mapping.xml 中的长度将根据您的要求而有所不同。
Spring Batch 为这个用例提供了 FixedLengthTokenizer
。您可以在此处的文档中阅读更多相关信息:http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/file/transform/FixedLengthTokenizer.html