安卓:SAX解析器进度监控
问题描述:
我有一个SAX
DefaultHandler,它解析一个InputStream。我不知道有多少元素在XML,所以我不能指望他们在endElement
或simmilar。我知道InputStream
(从http头中读取)的字节长度,但我找不到一种方法来获取解析过程的当前字节进度。安卓:SAX解析器进度监控
有没有办法让目前的进展分析过程中(即比特处理)?
这是DefaultHandler
被怎么称呼:
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(inputStream, myDefaultHandler);
答
您可以通过编写一个FilterInputStream来包装现有的inputStream做到这一点。在你的过滤器的方法read()
,增加一个计数器,并提供一个getter,使别的东西可以跟踪当前计数。
因为解析器可以读取提前,这将是近似的,但它可能是你能做的最好的。
答
对于任何人谁是仍在寻找答案, 尝试通过进度条在派生FilterInputStream的构造函数:
ProgressFilterInputStream.java
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import android.widget.ProgressBar;
import android.util.Log;
public class ProgressFilterInputStream extends FilterInputStream {
int counter = 0;
ProgressBar progressBar;
public ProgressFilterInputStream(InputStream in, ProgressBar progressBar) {
super(in);
this.progressBar = progressBar;
this.progressBar.setMax(69); // SET MAX ACCORDIN TO THE DDMS LOGGING MESSAGE
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
progressBar.setProgress(counter++);
Log.i("PFIS" , "Counter: " + counter);
return super.read(buffer, offset, count);
}
}
我用它在的AsyncTask我
MyActivity.java
final ProgressBar bar_progress = (ProgressBar) findViewById(R.id.bar_progress);
ProgressFilterInputStream pfis = new ProgressFilterInputStream(getAssets().open("DATA.xml") , bar_progress);
Reader reader = new InputStreamReader(pfis, "UTF-8");
InputSource is = new InputSource(reader);
// create the factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// create a parser
SAXParser parser = factory.newSAXParser();
// create the reader (scanner)
XMLReader xmlreader = parser.getXMLReader();
// instantiate our handler
SaxHandler myHandler = new SaxHandler();
// assign our handler
xmlreader.setContentHandler(myHandler);
// perform the synchronous parse
xmlreader.parse(is);
答
从lx222扩展回答,我实现了AsyncTask,ProgressDialog。后期,但我希望它可能有用一个:D
public class OpenXMLFileOperator extends AsyncTask<Void, Integer, Void>{
private ProgressDialog progressDialog;
private String filePath;
private Context context;
public OpenFileOperator(Context context,String filePath){
this.context = context;
this.filePath = filePath;
}
@Override
protected Void doInBackground(Void... arg0) {
try {
if (filePath != null) {
File file = new File(filePath);
if (file.exists()) {
InputStream stream = new FileInputStream(file);
ProgressFilterInputStream pfis = new ProgressFilterInputStream(stream,file.length());
Reader reader = new InputStreamReader(pfis, "UTF-8");
YourXMLHandle yourHandle = new YourXMLHandle();
android.util.Xml.parse(reader,yourHandle);
stream.close();
reader.close();
pfis.close();
}
}
}catch (Exception e) {
if (BuildConfig.DEBUG) Log.e(TAG, "Exception", e);
}
return null;
}
@Override
protected void onPreExecute() {
try{
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading file");
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(false);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
}catch(Exception e){
if (BuildConfig.DEBUG) Log.e(TAG,"onPostExecute",e);
}
super.onPreExecute();
}
@Override
protected void onCancelled() {
try{
if (progressDialog!=null && progressDialog.isShowing()){
progressDialog.dismiss();
}
}catch(Exception e){
if (BuildConfig.DEBUG) Log.e(TAG,"onPostExecute",e);
}
super.onCancelled();
}
@Override
protected void onPostExecute(Void result) {
try{
if (progressDialog!=null && progressDialog.isShowing()){
progressDialog.dismiss();
}
}catch(Exception e){
if (BuildConfig.DEBUG) Log.e(TAG,"onPostExecute",e);
}
//TODO: to do something after file loaded
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Integer... values) {
int progress = values[0];
if (progressDialog!=null) {
progressDialog.setProgress(progress);
}
super.onProgressUpdate(values);
}
private class ProgressFilterInputStream extends FilterInputStream {
private int counter = 0;
private long fileLength;
private int maximum = 100;
public ProgressFilterInputStream(InputStream in, long fileLength) {
super(in);
this.fileLength = fileLength;
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
if (counter==0){
maximum = (int)(fileLength/buffer.length);
}
publishProgress((counter++)*100/maximum);
return super.read(buffer, offset, count);
}
}
}
很好的想法,但我如何访问我的`FilterInputStream`从解析器内?或者我应该创建一个**定时器**,它从外部somwhere调用getter并根据情况更新状态? – Mannaz 2011-02-16 17:51:07