【问题标题】:Android: SAX parser progress monitoringAndroid:SAX 解析器进度监控
【发布时间】:2011-06-28 07:14:33
【问题描述】:

我有一个解析 InputStream 的 SAX DefaultHandler。我不知道 XML 中有多少元素,所以我不能指望它们在 endElement 或类似的。我确实知道 InputStream 的字节长度(从 http 标头读取),但我找不到获取解析过程当前字节进度的方法。

有没有办法获取解析过程的当前进度(即处理的位)?

DefaultHandler 的调用方式如下:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(inputStream, myDefaultHandler);

【问题讨论】:

    标签: android xml sax saxparser


    【解决方案1】:

    对于仍在寻找答案的任何人, 尝试在派生的 FilterInputStream 的构造函数中传递 ProgressBar:

    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);
    

    【讨论】:

      【解决方案2】:

      从 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);
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        您可以通过编写 FilterInputStream 来包装现有的 inputStream 来做到这一点。在过滤器的 read() 方法中,增加一个计数器,并提供一个 getter,以便其他东西可以跟踪当前计数。

        由于解析器可能会提前读取,这将是近似值,但这可能是您能做的最好的。

        【讨论】:

        • 好主意,但我如何从解析器中访问我的FilterInputStream?或者我应该创建一个 timer 从外面的某个地方调用 getter 并相应地更新状态?
        • 从外部执行,使其独立于解析本身。
        • 我尝试过这种方式,但是解析器在很长一段时间内都没有增加计数器,然后突然一次性消耗掉所有的InputStream。还有其他想法如何实现吗?
        • 我猜解析器在漫长的等待之后提前读取了很多!除了尝试通过正在发生的事情进行调试之外,无法立即想到更好的方法。在过滤器和处理程序中添加一些调试打印?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-01
        • 1970-01-01
        • 2014-06-11
        • 1970-01-01
        • 2011-08-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多