《转载》Android大TXT文本文档读取(续)

原文地址:http://wangliping.net/read-big-txt-2

 

上次写了个Android大TXT文本文档读取 , 但是提到不能往回读,这两天就顺手写了一下回翻的效果,当然回翻的时候鉴于手机CPU或者内存的缘故会觉得卡或者不卡,不过还好,自己测试的效果还行。倒 是一直在后台如果有个读取的备份的话,此处是指InputStreamReader对象的备份,而不是读取Buffer的备份。

 

  以下这段代码已经放到开源项目Filexpert 里了,在那个项目中,可以读取网络文件。大家如果感兴趣的话,也可以试试Filexpert,挺不错的一个项目,请大家多多支持。

  闲话少说,依旧上代码。

package net . wangliping . filemanager ;

import java.io.FileInputStream ;
import java.io.IOException ;
import java.io.InputStreamReader ;
import java.nio.CharBuffer ;

import android.app.Activity ;
import android.net.Uri ;
import android.os.AsyncTask ;
import android.os.Bundle ;
import android.os.Handler ;
import android.os.Message ;
import android.text.TextUtils ;
import android.util.Log ;
import android.widget.ScrollView ;

import com.swan.test.R ;

public class TxtReader extends Activity implements
        SwanTextView . OnPreDrawListener {

    private static final String LOG_TAG = "TxtReader" ;
    private static final int BUF_SIZE = 1024 * 2 ;
    private static final int BUF_SHOW = 3 ;
   
    private static final int ARROW_UP = 1 ;
    private static final int ARROW_DOWN = 2 ;

    private static String ENCODING = "GB2312" ;
   
    private InputStreamReader mIsReader = null ;
    private Uri mUri = null ;
    private SwanTextView mTextShow ;
    private ScrollView mScrollView ;
    private String mStringShow = null ;
    private StringBuilder mStringBuilder = null ;

    private boolean mReadNext     = true ;
    private boolean mReadBack     = false ;
    private boolean mStopThread   = false ;
   
    private int mPreBottom   = - 1 ;
    private int mCurBottom   = - 1 ;
    private int mReadBufNum = 0 ;
    private int mBuffHeight = - 1 ;
    private int mPreScrollY = - 1 ;

    private final Handler mHandler = new Handler () {
        @Override
        public void handleMessage (Message msg ) {
            switch (msg . what ) {
            case ARROW_DOWN:
                mTextShow . setText ((CharBuffer ) msg . obj );
                break ;
            case ARROW_UP:
                mTextShow . setText ((CharBuffer ) msg . obj );
                mScrollView . scrollTo (0 , mBuffHeight );
                break ;
            default :
                super . handleMessage (msg );
            }
        }
    };

    public void onCreate (Bundle savedInstanceState ) {
        super . onCreate (savedInstanceState );
        setContentView (R . layout . txt_reader );

        mUri = getIntent (). getData ();
       
        mScrollView = (ScrollView ) findViewById (R . id . text_show_scroll );

        mTextShow = (SwanTextView ) findViewById (R . id . text_show );   
        mTextShow . setOnPreDrawListener (this );

        new TextShowTask (). execute (mUri );
    }

    private void showText (Uri uri ) throws IOException , InterruptedException {
       
        mIsReader = new InputStreamReader (new FileInputStream (
                uri . getPath ()), ENCODING );
       
        mStringBuilder = new StringBuilder ();
        int initBufSize = BUF_SIZE * (BUF_SHOW - 1 );
        char [] buf = new char [ BUF_SIZE ];
       
        while (! mStopThread ) {
            int scrollY = mScrollView . getScrollY ();
            if (mCurBottom == scrollY && mPreScrollY < scrollY ) {
                mReadNext = true ;
                mReadBack = false ;
            } else if (mReadBufNum > BUF_SHOW && 0 == scrollY && mPreScrollY != scrollY ) {
                mReadNext = false ;
                mReadBack = true ;
            }
           
            mPreScrollY = scrollY ;

            int len = - 1 ;
            if (mReadNext && (len = mIsReader . read (buf )) > 0 ) {
                mReadNext = false ;
                mReadBufNum ++;

                if (mStringBuilder . length () > initBufSize ) {
                    mStringBuilder . delete (0 , BUF_SIZE );
                    mPreBottom = mCurBottom ;

                    Message msg = mHandler . obtainMessage (ARROW_DOWN );               
                    msg . obj = CharBuffer . wrap (mStringBuilder . toString ());
                    mHandler . sendMessage (msg );

                    mStringShow = mStringBuilder . append (buf , 0 , len ). toString ();
                } else {
                    while (mStringBuilder . length () < initBufSize ) {
                        mStringBuilder . append (buf );
                        mIsReader . read (buf );
                        mReadBufNum ++;
                    }

                    mStringBuilder . append (buf );
                    Message msg = mHandler . obtainMessage (ARROW_DOWN );
                    msg . obj = CharBuffer . wrap (mStringBuilder . toString ());
                    mHandler . sendMessage (msg );
                }
            } else if (mReadBack && mReadBufNum > BUF_SHOW ) {
                Log . d (LOG_TAG , "Prepare to read back" );
                mReadBack = false ;
                mIsReader . close ();
                new BackBufReadThread (mStringBuilder ). start ();
            }
        }
    }

    private class TextShowTask extends AsyncTask < Object , Object , Object > {
        @Override
        protected void onPostExecute (Object param ) {
            Log . d (LOG_TAG , "Send broadcast" );
        }

        @Override
        protected Object doInBackground (Object ... params ) {
            Uri uri = (Uri ) params [ 0 ];

            try {
                showText (uri );
            } catch (Exception e ) {
                Log . d (LOG_TAG , "Exception" , e );
            }

            return null ;
        }
    }
   
    private class BackBufReadThread extends Thread {
        StringBuilder mSbPre = null ;
       
        public BackBufReadThread (StringBuilder sb) {
            mSbPre = sb. delete (0 , sb. length ());
        }
       
        @Override
        public void run () {
            try {
                mIsReader = new InputStreamReader (new FileInputStream (
                        mUri . getPath ()), ENCODING );
               
                char [] buf = new char [ BUF_SIZE ];
                int i = 0 ;
                while ((mReadBufNum - BUF_SHOW ) > ++ i && mIsReader . read (buf ) > 0 ) {
                    // Just to skip the inputstream. Any better methods?
                }
                mReadBufNum --;
               
                for (i = 0 ; i < BUF_SHOW ; i ++) {
                    mIsReader . read (buf );                   
                    mSbPre . append (buf );
                }
               
               
//                mSbPre.delete(mSbPre.length() - BUF_SIZE, mSbPre.length()).insert(0, buf);
                Message msg = mHandler . obtainMessage (ARROW_UP );
                msg . obj = CharBuffer . wrap (mSbPre . toString ());
                mHandler . sendMessage (msg );
            } catch (Exception e ) {
                Log . d (LOG_TAG , "Exception" , e );
            }
        }
    }

    @Override
    public void onPreDraw (int bottom ) {
        mCurBottom = bottom - mScrollView . getHeight ();
       
        if (! TextUtils . isEmpty (mStringShow )) {
            // Use the last deleted buff to evaluate the height
            mBuffHeight = mPreBottom - mScrollView . getScrollY ();
           
            // Set the text to add new content without flash the view
            Message msg = mHandler . obtainMessage (ARROW_DOWN );
            msg . obj = CharBuffer . wrap (mStringShow );           
            mHandler . sendMessage (msg );
           
            mStringShow = null ;
        }
    }
   
    @Override
    public void finish () {
        mStopThread = true ;
        super . finish ();
    }
}

  资源文件和SwanTextView跟上次的文章一样,只不过为了名字命名好看点,把SwanTextView里的响应函数改成如下了:

@Override
protected void onDraw ( Canvas canvas ) {
   
    if ( mPreBottom != getBottom ()) {
        mPreBottom = getBottom ();

        if (preDrawListener != null )
            preDrawListener . onPreDraw (mPreBottom );
    }

    super . onDraw (canvas );
}

public static interface OnPreDrawListener {
    public void onPreDraw (int bottom );
}

public void setOnPreDrawListener (OnPreDrawListener listener ) {
    preDrawListener = listener ;
}

  代码不成熟,见笑了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值