为什么我的 Sax 解析器在使用 InputStream Read 后没有产生结果?
-
22-09-2019 - |
题
我有这段代码,我希望它能够告诉我已经下载了多少数据(并很快将其放入进度条中),然后通过我的 Sax 解析器解析结果。如果我基本上注释掉上面的所有内容 //xr.parse(new InputSource(request.getInputStream())); 行并交换 xr.parse 的结束,它工作正常。但目前,我的 Sax 解析器告诉我我什么都没有。是不是跟是有关系。读 (缓冲区)部分?
另外,请注意,请求是具有各种签名的 HttpURLConnection。
/*Input stream to read from our connection*/
InputStream is = request.getInputStream();
/*we make a 2 Kb buffer to accelerate the download, instead of reading the file a byte at once*/
byte [ ] buffer = new byte [ 2048 ] ;
/*How many bytes do we have already downloaded*/
int totBytes,bytes,sumBytes = 0;
totBytes = request.getContentLength () ;
while ( true ) {
/*How many bytes we got*/
bytes = is.read (buffer);
/*If no more byte, we're done with the download*/
if ( bytes <= 0 ) break;
sumBytes+= bytes;
Log.v("XML", sumBytes + " of " + totBytes + " " + ( ( float ) sumBytes/ ( float ) totBytes ) *100 + "% done" );
}
/* Parse the xml-data from our URL. */
// OLD, and works if comment all the above
//xr.parse(new InputSource(request.getInputStream()));
xr.parse(new InputSource(is))
/* Parsing has finished. */;
任何人都可以帮助我吗?
亲切的问候,
安迪
解决方案
“除非您知道另一种方法,否则我只能找到一种使用字节来做到这一点的方法吗?”。
但是你 没有 找到了一个方法。您刚刚编写了不起作用的代码。而且您也不想将输入保存到字符串中。你想要计算字节数 当你解析它们时。 否则你只是增加延迟,即浪费时间并减慢一切。有关如何正确执行此操作的示例,请参阅 javax.swing.ProgressMonitorInputStream。您不必使用它,但您肯定必须使用某种 FilterInputStream,可能是您自己编写的,它包裹在请求输入流中并传递给解析器。
其他提示
您的 while 循环正在消耗输入流,并且没有留下任何内容供解析器读取。
对于您想要做的事情,您可能需要考虑实现包装输入流的 FilterInputStream 子类。
您正在构建一个 InputStream
超过另一个 InputStream
之前消耗过它的数据。
如果你想避免只读取单个字节,你可以使用 BufferedInputStream
或不同的东西,比如 BufferedReader
.
无论如何,最好在解析之前获取全部内容!除非你需要动态解析它。
如果你真的想像现在一样保持它,你应该创建两个管道流:
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream();
pipeIn.connect(pipeOut);
pipeOut.write(yourBytes);
xr.parse(pipeIn);
Java 中的流,就像它们的名字所暗示的那样,没有精确的维度,你也不知道它们何时结束,所以每当你创建一个流时, InputStream
, ,如果你读了它们,你就不能通过相同的 InputStream
到另一个对象,因为数据已经从前一个对象中被消耗。
如果你想同时做这两件事(下载和解析),你必须在从接收到的数据之间进行挂钩 HTTPUrlConncection
你应该:
- 首先知道正在下载的数据的长度,这可以从
HttpUrlConnection
标头 - 使用自定义的 InputStream 进行装饰(这是流在 Java 中的工作方式,请参阅 这里)更新进度条..
就像是:
class MyInputStream extends InputStream
{
MyInputStream(InputStream is, int total)
{
this.total = total;
}
public int read()
{
stepProgress(1);
return super.read();
}
public int read(byte[] b)
{
int l = super.read(b);
stepProgress(l);
return l;
}
public int read(byte[] b, int off, int len)
{
int l = super.read(b, off, len);
stepProgress(l);
return l
}
}
InputStream mis= new MyInputStream(request.getInputStream(), length);
..
xr.parse(mis);
您可以将数据保存在文件中,然后将其读出。
InputStream is = request.getInputStream();
if(is!=null){
File file = new File(path, "someFile.txt");
FileOutputStream os = new FileOutputStream(file);
buffer = new byte[2048];
bufferLength = 0;
while ((bufferLength = is.read(buffer)) > 0)
os.write(buffer, 0, bufferLength);
os.flush();
os.close();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
FileInputStream fis = new FileInputStream(file);
xpp.setInput(new InputStreamReader(fis));
}