文件名包含#导致Spring Batch StaxEventItemReader无法打开

我有一个名为(UPX#L.xxxxx001.xml)中的#的input文件。 Spring批处理StaxEventItemReader未能打开这个文件。 无论如何逃避这个特殊的angular色? 请指教。

这是我的豆子

<bean id="myItemReader" parent="myItemReaderParent" scope="step"> <property name="resource" value="file:#{jobParameters['toolf.input.file.name']}"/> </bean> <bean id="myItemReaderParent" class="org.springframework.batch.item.xml.StaxEventItemReader" scope="prototype"> <property name="fragmentRootElementName" value="MyRec"/> <property name="unmarshaller" ref="myUnmarshaller"/> </bean> 
 [INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,487] - Sending notification for start of JobExecution: id=52760, version=1, startTime=Thu Feb 05 10:27:23 EST 2015, endTime=null, lastUpdated=Thu Feb 05 10:27:23 EST 2015, status=STARTED, exitStatus=exitCode=UNKNOWN;exitDescription=, job=[JobInstance: id=52759, version=0, JobParameters=[ {toolf.institutionSymbol=YDX , toolf.projectId=013832, toolf.orderId=678161, toolf.transmissionDate=20150205 10:27:23.392 EST, toolf.input.file.name=/batchdata/dataload/xxx/in/tool/UPX#L.xxxxx001.xml, toolf.out.root.directory=/batchdata/output, toolf.out.input.file.name.without.path=YDX.013832.678161.YbpUsSI#Picklists.d20150204.t140001.xml, toolf.out.working.directory/batchdata/dataload/xxx/in/tool/, timestamp=1423150043392} ], Job=[timeOfOrderLabelJob]] [INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,576] - Executing step: [toolPrologue] [ERROR]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,607] - Encountered an error executing the step org.springframework.batch.item.ItemStreamException: Failed to initialize the reader at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:137) at sun.reflect.GeneratedMethodAccessor260.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy9.open(Unknown Source) at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:93) at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:301) at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:192) at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135) at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61) at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60) at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144) at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124) at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135) at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281) at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120) at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48) at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:229) at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129) at org.oclc.tool.mule.launch.MuleJobLauncher.launchJob(MuleJobLauncher.groovy:74) at org.oclc.tool.mule.launch.JobLauncher$launchJob.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:137) at org.oclc.tool.mule.si.JmsMessageUnwrapper.unwrapMessage(JmsMessageUnwrapper.groovy:42) at sun.reflect.GeneratedMethodAccessor596.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69) at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:83) at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57) at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102) at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126) at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:225) at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:125) at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:73) at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:64) at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:98) at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78) at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:110) at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97) at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:61) at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157) at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288) at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149) at org.springframework.integration.core.MessagingTemplate.convertAndSend(MessagingTemplate.java:189) at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:183) at org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate.send(ChannelPublishingJmsMessageListener.java:424) at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:278) at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:535) at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:495) at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947) at java.lang.Thread.run(Thread.java:619) Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode) at org.springframework.batch.item.xml.StaxEventItemReader.doOpen(StaxEventItemReader.java:182) at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:134) ... 73 more [INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,612] - enter DetailLogStepExecutionListener.afterStep [INFO ]org.springframework.jms.listener.DefaultMessageListenerContainer#0-1[2015-02-05 10:27:23,612] - exit DetailLogStepExecutionListener.afterStep 

在URL / URI中 , #字符是保留的,用于分隔片段标识符 (对file: resource方案没有任何意义)。 如果你想包含这个字符作为路径的一部分,它必须用%23转义

而不是将你的价值连接到file:在你的bean定义文件中,我建议你将参数指定为完整的URI / URI,而不是文件系统路径:

 <property name="resource" value="#{jobParameters['toolf.input.file.url']}"/> 

并将toolf.input.file.url设置为:

 file:/batchdata/dataload/xxx/in/tool/UPX%23L.xxxxx001.xml 

这将避免你可能遇到的其他擒纵陷阱,比如字符@ !=

如果您必须使用文件系统路径作为参数,则应该能够使用:

 <property name="resource" value="#{new java.io.File(jobParameters['toolf.input.file.name']).toURI().toURL()}"/> 

从看你的错误信息和回答,你的问题是清楚的,Tunaki和Glenn Lane都是部分正确的,我正在投票Glenn Lane回答你提出的问题,并且做得很好。

从你的回复到Glenn:

if(fileName.contains(“#”)){def(value1,value2)= fileName.split(“#”)fileName = value1 +“%23#”+ value2}我试过这个。 依然不起作用

逃避不利于情况。

这个角色已经在执行链的某个地方被处理了,Tunaki正确地质疑了你所遇到的类型错误。

从您的错误日志中:

[错误] org.springframework.jms.listener.DefaultMessagelistnerContainer#0-1 [2015-02-05 10:27:23,607] – 遇到执行步骤的错误org.springframework.batch.item.ItemStreamException:无法初始化读者

再加上Tunaki指出的资源状态例外,我们可以得出结论是这样的。 这里没有足够的信息来说明这种情况为什么发生,但是这里有两个大类:

  1. 根据文件存储到达或来自文件存储的方式,字符可能已经在该进程中的该文件中被删除,或者以文件处理程序无法处理的方式在存储上被别名化。 出于Glenn指出的原因。

  2. 根据执行链中的消息或作业处理,在转换成URI / URL调用或转换成URI / URL时,将被删除。 出于Glenn指出的原因。

是。 这是#问题。 一旦#被删除它工作正常。

根据上面的说法,简单,快速和肮脏的解决方案应该意识到这一点,并根据需要通过从文件或uri中直接剥离和注入#来处理它。 根据你的代码片段,你知道如何做到这一点。

解决此问题的正确方法是跟踪资源错误发生的位置,并确保您的文件处理在整个作业流程中保持一致。

如果没有所有正确的代码和/或了解更多有关您的系统配置,我不能具体。 在bean和错误日志之间根本没有足够的信息来确切地说出现这种情况,而这只是你的问题。

以下是一些可能的建议:

我假设你已经检查了文件直接存储和手删除#和更改文件名称的作业,它运行,基于你的上述声明。

  1. 尝试使用相同的标识符访问不同Java对象的商店中的文件, 然后检查您的物品阅读器实现如何处理文件访问。

  2. 如果失败或者那不是失败点。 检查“#”值是否是作业文件,如果它在那里和/或唯一的#当您执行拆分。

  3. 如果所有的检查都发现它是如何到达文件存储的,那么这个资源可以在存储中正确定位,并且#也不是在你的实现中被保留,或者需要特殊的处理/配置。

这将有助于缩小根本原因。