MalformedByteSequenceException 使用 ROME 解析 RSS 提要
MalformedByteSequenceException parsing RSS feed with ROME
我得到一个 MalformedByteSequenceException 运行 一个使用 Rome Rss 解析库的 JSF 应用程序:
[2017-08-31T15:54:01.241+0200] [glassfish 5.0] [SEVERE] [] [] [tid: _ThreadID=101 _ThreadName=Thread-9] [timeMillis: 1504187641241] [levelValue: 1000] [[
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Ungültiges Byte 1 von 1-Byte-UTF-8-Sequenz.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:701)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:567)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1793)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipChar(XMLEntityScanner.java:1463)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2824)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
at main.java.tools.RssAggregator.searchAggregatedFeeds(RssAggregator.java:119)
at main.java.jobs.ApplicationRunnable.lambda$execute[=10=](ApplicationRunnable.java:45)
at java.lang.Iterable.forEach(Iterable.java:75)
at main.java.jobs.ApplicationRunnable.execute(ApplicationRunnable.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
]]
错误在RssAggregator.searchAggregatedFeeds()第119行抛出:
public List<Feed> searchAggregatedFeeds(String keyword) {
keyword = keyword.toLowerCase();
List<Feed> results = new LinkedList<>();
Document document = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//document = builder.parse(IOUtils.toInputStream(this.aggregatedRssString);
InputStream stream = new ByteArrayInputStream(this.aggregatedRssString.getBytes());
document = builder.parse(stream); //TODO HERE We have the Problem
stream.close();
//Normalize the XML Structure; It's just too important !!
document.getDocumentElement().normalize();
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
//Here comes the root node
if (document != null) {
//Element root = document.getDocumentElement();
//Get all
NodeList nList = document.getElementsByTagName("item");
for (int i = 0; i < nList.getLength(); i++) {
Node node = nList.item(i);
Element ele = (Element) node;
Feed feed = new Feed();
feed.setDate(ele.getElementsByTagName("dc:date").item(0).getTextContent());
feed.setDescription(ele.getElementsByTagName("description").item(0).getTextContent());
feed.setLink(ele.getElementsByTagName("link").item(0).getTextContent());
feed.setSubject(ele.getElementsByTagName("title").item(0).getTextContent());
feed.setId(getIdCounter()); //set the id. This increments also
/* now the searching ... */
if (feed.getSubject().toLowerCase().contains(keyword) || feed.getDescription().toLowerCase().contains(keyword))
results.add(feed);
}
}
return results;
}
我不知道 document = builder.parse(stream); //TODO HERE We have the Problem
?
这行有什么问题
这里让我印象深刻的是,当用 junit-test 测试它时,一切顺利:
@Test
public void searchTest() throws Exception {
List<Feed> results = rssAggregator.searchAggregatedFeeds("a");
System.out.println("Hits: " + results.size());
List<Feed> results2 = rssAggregator.searchAggregatedFeeds("z");
System.out.println("Hits: " + results2.size());
List<Feed> results3 = rssAggregator.searchAggregatedFeeds("x");
System.out.println("Hits: " + results3.size());
}
结果符合预期:
...从循环作业调用它时不会:
List<Feed> allResults = new LinkedList<>();
/* for each WORD search the aggregatedfeed for matches and add them to allResults */
configBean.words.forEach(w -> {
System.out.println("current searched for Word: " + w);
List<Feed> wResults = aggregator.searchAggregatedFeeds(w); // :(
allResults.addAll(wResults);
});
问题:为什么 junit-test 有效,而来自应用程序内部的调用却无效?汇总的提要完全相同。
您的 rss 数据是 UTF-8 编码的吗?调用 String.getBytes()
的无参数版本将使用平台的默认字符集,它可能不是 UTF-8。这就是为什么您的测试可能在 Linux 上运行但在 Windows 上失败的原因。请尝试 String.getBytes(Charset charset)
。
我得到一个 MalformedByteSequenceException 运行 一个使用 Rome Rss 解析库的 JSF 应用程序:
[2017-08-31T15:54:01.241+0200] [glassfish 5.0] [SEVERE] [] [] [tid: _ThreadID=101 _ThreadName=Thread-9] [timeMillis: 1504187641241] [levelValue: 1000] [[
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Ungültiges Byte 1 von 1-Byte-UTF-8-Sequenz.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:701)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:567)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1793)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipChar(XMLEntityScanner.java:1463)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2824)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
at main.java.tools.RssAggregator.searchAggregatedFeeds(RssAggregator.java:119)
at main.java.jobs.ApplicationRunnable.lambda$execute[=10=](ApplicationRunnable.java:45)
at java.lang.Iterable.forEach(Iterable.java:75)
at main.java.jobs.ApplicationRunnable.execute(ApplicationRunnable.java:43)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
]]
错误在RssAggregator.searchAggregatedFeeds()第119行抛出:
public List<Feed> searchAggregatedFeeds(String keyword) {
keyword = keyword.toLowerCase();
List<Feed> results = new LinkedList<>();
Document document = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//document = builder.parse(IOUtils.toInputStream(this.aggregatedRssString);
InputStream stream = new ByteArrayInputStream(this.aggregatedRssString.getBytes());
document = builder.parse(stream); //TODO HERE We have the Problem
stream.close();
//Normalize the XML Structure; It's just too important !!
document.getDocumentElement().normalize();
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
//Here comes the root node
if (document != null) {
//Element root = document.getDocumentElement();
//Get all
NodeList nList = document.getElementsByTagName("item");
for (int i = 0; i < nList.getLength(); i++) {
Node node = nList.item(i);
Element ele = (Element) node;
Feed feed = new Feed();
feed.setDate(ele.getElementsByTagName("dc:date").item(0).getTextContent());
feed.setDescription(ele.getElementsByTagName("description").item(0).getTextContent());
feed.setLink(ele.getElementsByTagName("link").item(0).getTextContent());
feed.setSubject(ele.getElementsByTagName("title").item(0).getTextContent());
feed.setId(getIdCounter()); //set the id. This increments also
/* now the searching ... */
if (feed.getSubject().toLowerCase().contains(keyword) || feed.getDescription().toLowerCase().contains(keyword))
results.add(feed);
}
}
return results;
}
我不知道 document = builder.parse(stream); //TODO HERE We have the Problem
?
这里让我印象深刻的是,当用 junit-test 测试它时,一切顺利:
@Test
public void searchTest() throws Exception {
List<Feed> results = rssAggregator.searchAggregatedFeeds("a");
System.out.println("Hits: " + results.size());
List<Feed> results2 = rssAggregator.searchAggregatedFeeds("z");
System.out.println("Hits: " + results2.size());
List<Feed> results3 = rssAggregator.searchAggregatedFeeds("x");
System.out.println("Hits: " + results3.size());
}
结果符合预期:
...从循环作业调用它时不会:
List<Feed> allResults = new LinkedList<>();
/* for each WORD search the aggregatedfeed for matches and add them to allResults */
configBean.words.forEach(w -> {
System.out.println("current searched for Word: " + w);
List<Feed> wResults = aggregator.searchAggregatedFeeds(w); // :(
allResults.addAll(wResults);
});
问题:为什么 junit-test 有效,而来自应用程序内部的调用却无效?汇总的提要完全相同。
您的 rss 数据是 UTF-8 编码的吗?调用 String.getBytes()
的无参数版本将使用平台的默认字符集,它可能不是 UTF-8。这就是为什么您的测试可能在 Linux 上运行但在 Windows 上失败的原因。请尝试 String.getBytes(Charset charset)
。