向虚拟机sk卡复制文件 adb push aaa.txt /sdcard/book.txt
BigTextReader代码:
package dingq.BigTxtReader;
// Android大TXT文本文档读取
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;
public class BigTxtReader extends Activity implements
SwanTextView.OnPreDrawListener {
private static final String LOG_TAG = "BigTxtReader";
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.main);
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];
uri = Uri.parse("/sdcard/books/aaa.txt");
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);
}
}
}
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
package dingq.BigTxtReader;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.TextView;
public class SwanTextView extends TextView {
private int mPreBottom = -1;
private OnPreDrawListener preDrawListener = null;
public SwanTextView(Context context) {
super(context);
}
public SwanTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwanTextView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
@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;
}
}
布局main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text_show_linear" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ScrollView android:id="@+id/text_show_scroll"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<dingq.BigTxtReader.SwanTextView
android:id="@+id/text_show" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:scrollbars="none">
</dingq.BigTxtReader.SwanTextView>
</ScrollView>
</LinearLayout>
Mainfest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dingq.BigTxtReader"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".BigTxtReader"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>