Android:SAX解析器进度监控

发布于 2024-10-17 19:08:29 字数 559 浏览 5 评论 0原文

我有一个 SAX DefaultHandler 解析输入流。我不知道 XML 中有多少个元素,因此无法根据 endElement 或 simmilar 来计算它们。我确实知道InputStream的字节长度(从http标头读取),但我找不到获取解析过程当前字节进度的方法。

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

这是 DefaultHandler 的调用方式:

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

I have a SAX DefaultHandler which parses an InputStream. I don't know how many elements are in the XML so I can't count them on endElement or simmilar. I do know the byte length of the InputStream (read from the http header) but I can't find a method to get the current bytewise progress of the parsing process.

Is there a way to get the current progress (i.e. bits processed) of the parsing process?

This is how the DefaultHandler gets called:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

渔村楼浪 2024-10-24 19:08:29

对于仍在寻找答案的人来说,
尝试在派生的 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);

For anyone who is still searching for the answer,
try to pass the ProgressBar in the constructor of your derived 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);
}
}

I used it in an AsyncTask in my

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);
烟酒忠诚 2024-10-24 19:08:29

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

Extended from lx222 answer, I implemented for AsyncTask, ProgressDialog. Late but I hope it may useful with some one :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);
        }
    }
}
坏尐絯℡ 2024-10-24 19:08:29

您可以通过编写 FilterInputStream 来完成此操作包装现有的输入流。在过滤器的 read() 方法中,增加一个计数器,并提供一个 getter,以便其他东西可以跟踪当前计数。

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

You can do this by writing a FilterInputStream to wrap the existing inputStream. In the read() method of your filter, increment a counter, and provide a getter so that something else can track the current count.

Since the parser may read ahead, this will be approximate, but it's probably the best you can do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文