一、简述
一个简单的txt文本编辑器。
工程打包:链接:https://pan.baidu.com/s/1CsszQVde5QAiQVMu2fC63w 密码:qyjt
二、效果
三、工程结构
四、源文件
TxtReader.java文件
package com.mypackage.MyNotepad;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import com.ostrichmyself.txtReader.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.text.InputFilter;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridLayout;
import android.widget.TextView;
import android.widget.Toast;
public class TxtReader extends Activity implements OnClickListener {
/** Called when the activity is first created. */
private String filePath = "";//保存文件的绝对路径
private String fileName = "";//文件名
private static final String defaultCode = "UTF8";//默认编码
@SuppressLint("NewApi") @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//设置为没有标题栏,自定义一个标签作为标题
setContentView(R.layout.main);//设置布局
//获取控件对象,并监听点击事件
Button fileOpenBtn = (Button)findViewById(R.id.btn_open);
fileOpenBtn.setOnClickListener(new OpenFileAction());
Button btnexit = (Button)findViewById(R.id.btn_exit);
btnexit.setOnClickListener(this);
Button btnsave = (Button)findViewById(R.id.btn_save);
btnsave.setOnClickListener(this);
Button btnsaveas = (Button)findViewById(R.id.btn_saveas);
btnsaveas.setOnClickListener(this);
Button btnfind = (Button)findViewById(R.id.btn_find);
btnfind.setOnClickListener(this);
Button btnnew = (Button)findViewById(R.id.btn_new);
btnnew.setOnClickListener(this);
//
//
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override //子页面返回时执行
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 1 && resultCode == 1){//有多个页面时根据请求码和结果码判断是哪一个子页面结束返回,并相应的做出响应
try {
Bundle bunde=data.getExtras();//获取数据束
filePath = bunde.getString("path");//类似于键值对,根据键"path"获取对应的值(子页面传回来的数据)
fileName = filePath.substring(filePath.lastIndexOf("/")+1,filePath.length());//根据绝对路径得到文件名,(用来设置标题)
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取便签对象,作为标题
tvtitle.setText(fileName+"-我的记事本");//设置文本
EditText tv = (EditText) findViewById(R.id.edt_contents);//获取到多行编辑框
String fileContent = getStringFromFile(defaultCode);//获取到文件内容
tv.setText(fileContent);//将编辑框的内容设置为文件内容
} catch (Exception e)
{
Toast.makeText(this, "获取数据异常",Toast.LENGTH_SHORT).show();
}
}
}
public String getStringFromFile(String code)//按照一定的编码格式读取txt文件
{
try {
StringBuffer sBuffer = new StringBuffer();//用来存放文件内容
FileInputStream fInputStream = new FileInputStream(filePath);//根据绝对路径创建数据流
InputStreamReader inputStreamReader = new InputStreamReader(fInputStream, code);
BufferedReader in = new BufferedReader(inputStreamReader);
if(!new File(filePath).exists())//如果文件不存在
{
in.close();//关闭流
return null;//直接返回
}
while (in.ready()) {
sBuffer.append(in.readLine() + "\n");//一行一行的读取,并追加到sBuffer中
}
in.close();//关闭流
return sBuffer.toString();//返回文件内容
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
class OpenFileAction implements OnClickListener
{
public void onClick(View v) {//这是另外一种方式实现监听
//"打开"按钮的监听事件处理,跳转到文件列表
Intent in = new Intent(TxtReader.this, ListAllFileActivity.class);
startActivityForResult(in, 1);//设置请求码为1
}
}
@SuppressLint("NewApi")
@Override
public void onClick(View arg) {//监听事件处理
switch (arg.getId())
{
case R.id.btn_new://新建按钮
EditText tv = (EditText) findViewById(R.id.edt_contents);//获取到文本编辑框对象
tv.setText("");//清空内容
filePath = "";//清空路径
fileName = "";//清空文件名
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取到标题标签
tvtitle.setText("未命名.txt-我的记事本");//设置文本
break;
case R.id.btn_save://保存按钮
if(fileName.isEmpty())//文件名为空,说明是新建文件(未命名)
{
//弹出对话框,让用户输入文件名
AlertDialog.Builder builderExit = new AlertDialog.Builder(this);
builderExit.setTitle("保存"); //对话框标题
builderExit.setMessage("请输入文件名!");//对话框提示信息
final EditText edtname = new EditText(this);//创建一个输入框对象
edtname.setSingleLine();//设置为单行输入
edtname.setText("未命名.txt");//设置文本
edtname.setSelection(0, 3);//选中文本的第0开始的3个字符(就是选中"未命名"3个字符)
edtname.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置输入最大长度
});
builderExit.setView(edtname);//将输入框添加到对话框
builderExit.setNegativeButton("取消",null); //添加取消按钮
//添加确定按钮,并且添加单击事件处理
builderExit.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = edtname.getText().toString().trim();//获取输入框的文本内容,并去掉前后空格
if(!(name.isEmpty()))//如果输入的文件名不为空
{
if(!name.endsWith(".txt"))//文件名没有以".txt"结尾
{
name += ".txt";//在结尾处添加".txt"
}
fileName = name;//更新为当前文件名
//获取文本编辑框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//将文本编辑框内容保存到文件
boolean b = Save(name,edtcontent.getText().toString(),true);
if(b)
{
TextView tvtitle = (TextView)findViewById(R.id.tv_title);//获取到标题标签
tvtitle.setText(fileName+"-我的记事本");//设置文本
//弹出小黑框提示
Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
}
else//文件名为空
{
//提示
Toast.makeText(TxtReader.this,"文件名不能为空",Toast.LENGTH_SHORT).show();
}
}
});
builderExit.show();//弹出保存对话框
}
else //文件名不为空,说明是打开的文件,或者是已经保存过一次的文件
{
if(!fileName.endsWith(".txt"))//文件名不以".txt"结尾
{
fileName += ".txt";//在结尾加上".txt"
}
//获取文本输入框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//获取文本输入框的内容
String txt = edtcontent.getText().toString();
//System.out.println(txt);
//覆盖保存到文件中,
boolean b = Save(fileName,txt,false);
//提示保存成功
if(b)Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_saveas://另存为按钮
if(true)
{
//弹出文件两寸为对话框
AlertDialog.Builder builderExit = new AlertDialog.Builder(this);
builderExit.setTitle("另存为");//设置标题
builderExit.setMessage("请输入文件名!");//设置提示信息
final EditText edtname = new EditText(this);//创建文本输入框对象
edtname.setSingleLine();//设置为单行输入
if(filePath.isEmpty())//如果原来文件名为空,说明是新建文件
{
edtname.setText("未命名.txt");//设置文本(初始文件名)
edtname.setSelection(0, 3);//选中"未命名"3个子符
}
else //如果原来文件名不为空,说明是不是新建文件
{
//确保文件名是以".txt"结尾的
if(!fileName.endsWith(".txt"))
{
fileName += ".txt";
}
edtname.setText(fileName);//将文本框初始文本为原来的文件名
int top = fileName.indexOf(".txt")+1;
edtname.setSelection(0, top);//选中原来的文件名
}
edtname.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置最大文件名长度
});
builderExit.setView(edtname);//将编辑框添加到另存为对话框
builderExit.setNegativeButton("取消",null); //添加取消按钮
//添加确定按钮,并监听点击事件
builderExit.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String name = edtname.getText().toString().trim();//获取输入框的内容并去掉两端的空格
if(!(name.isEmpty()))//如果文件名不为空
{
//确保文件名以".txt"结尾
if(!name.endsWith(".txt"))
{
name += ".txt";
}
fileName = name;//设置当前文件名
//获取文本输入框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
//将文件内容覆盖保存
boolean b = Save(name,edtcontent.getText().toString(),false);
//提示保存成功
if(b) Toast.makeText(TxtReader.this,"已保存",Toast.LENGTH_SHORT).show();
}
else//文件名为空
{
Toast.makeText(TxtReader.this,"文件名不能为空",Toast.LENGTH_SHORT).show();
}
}
});
builderExit.show();//弹出另存为对话框
}
break;
case R.id.btn_find://查找按钮
//查找、替换对话框
AlertDialog.Builder builder = new AlertDialog.Builder(TxtReader.this);
builder.setTitle("查找/替换"); //设置标题
//创建一个网格布局
GridLayout grid = new GridLayout(TxtReader.this);
grid.setColumnCount(2);//设置列数
//创建替换为标签
TextView viewrpl = new TextView(TxtReader.this);
viewrpl.setText("替换为:");//设置文本
//创建替换文本输入框
final EditText edtrpl = new EditText(TxtReader.this);
edtrpl.setSingleLine();//设置为单行
edtrpl.setHeight(45);//设置高度
edtrpl.setPadding(3, 0, 3, 0);//设置内边距,左上右下
edtrpl.setHint("请输入要替换为的字符");//设置初始文本(获取焦点是次文本消失)
edtrpl.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置最大长度
});
grid.addView(viewrpl, 0);//将替换为标签添加到网格布局的第0列
grid.addView(edtrpl, 1);//将替换为输入框添加到网格布局的第1列
//创建查找标签
TextView viewfind = new TextView(TxtReader.this);
viewfind.setText("查找:");//设置文本
//创建查找输入框
final EditText edtfind = new EditText(TxtReader.this);
edtfind.setSingleLine();//设置为单行
edtfind.setHeight(45);//设置高度
edtfind.setPadding(3, 0, 3, 0);//设置内边距
edtfind.setHint("请输入要查找的字符");//设置初始字符
edtfind.setFilters(new InputFilter[]{
new InputFilter.LengthFilter(64)//设置最大长度
});
grid.addView(viewfind, 0);//将查找标签添加到网格布局的第0列
grid.addView(edtfind, 1);//将查找输入框添加到网格布局的第1列
builder.setView(grid);//将网格布局添加到对话框
builder.setNegativeButton("取消",null); //添加取消按钮
//添加查找按钮并监听点击事件
builder.setNeutralButton("查找", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String findStr = edtfind.getText().toString();//获取到要查找的文本
if(findStr.isEmpty())//为空,什么都不做
{
}
else//不为空
{
//获取文本编辑框对象
EditText edtcontent = (EditText) findViewById(R.id.edt_contents);
int start = -1;//选中文本的开始索引
//在全部内容中查找目标,并记下找到的开始位置
start = edtcontent.getText().toString().indexOf(findStr);
if(start != -1)//已经找到
{
int stop = start+findStr.length();//选中文本的结束索引
edtcontent.setSelection(start, stop);//将找到的文本选中
//提示找到
Toast.makeText(TxtReader.this,"已找到!",Toast.LENGTH_SHORT).show();
}
else//未找到
{
Toast.makeText(TxtReader.this,"未找到!",Toast.LENGTH_SHORT).show();
}
}
}
});
//添加替换按钮
builder.setPositiveButton("替换", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String rplstr = edtrpl.getText().toString();//获取到要替换为的文本
Toast.makeText(TxtReader.this,"替换成功!",Toast.LENGTH_SHORT).show();
}
});
builder.show(); //弹出对话框
break;
case R.id.btn_exit://退出按钮
//退出确认对话框
AlertDialog.Builder builderExit = new AlertDialog.Builder(this);
builderExit.setTitle("退出"); //标题
builderExit.setMessage("您确定退出吗?");//提示信息
builderExit.setNegativeButton("取消",null);//添加取消按钮
//添加确定按钮
builderExit.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();//关闭页面
}
});
builderExit.show();
break;
}
}
//保存到文件 filename:文件名 content:内容 isAppend:是否追加,(否则覆盖)
public static boolean Save(String filename,String content,boolean isAppend)
{
//在文本文本中追加内容
String sdCardDir =Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(sdCardDir,filename);
//System.out.println(sdCardDir);
BufferedWriter out = null;
try {
if(!file.exists())//文件不存在
{
file.createNewFile();//创建新文件
}
FileOutputStream outStream = new FileOutputStream(file,isAppend);
outStream.write(content.getBytes());//写入文件
outStream.close();//关闭流
System.out.println("save success!");
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(out != null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
ListAllFileActivity.java文件
package com.mypackage.MyNotepad;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.ostrichmyself.txtReader.R;
import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/*展现全部文件的Activity*/
public class ListAllFileActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.filelist);//设置布局
//初始化文件列表
File path = android.os.Environment.getExternalStorageDirectory();
File[] f = path.listFiles();
fill(f);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {//菜单
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override //选项点击事件
protected void onListItemClick(ListView l, View v, int position, long id) {
//bundle = new Bundle();
File file = fileNameList.get(position);
if (file.isDirectory())//如果是文件夹,则进入
{
File[] f = file.listFiles();
fill(f);
}
else //如果是文件
{
//将选中的文件的绝对路径返回给主页面
Intent intent = new Intent(ListAllFileActivity.this, TxtReader.class);
//bundle.putString(fileNameKey, file.getAbsolutePath());
intent.putExtra("path",file.getAbsolutePath());
setResult(1, intent);//设置返回码为1
finish();
}
}
// 读取文件列表,并设置listview
private void fill(File[] files) {
fileNameList = new ArrayList<File>();
for (File file : files) {
if (isValidFileOrDir(file)) {
fileNameList.add(file);
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, fileToStrArr(fileNameList));
setListAdapter(adapter);
}
/*检查是否为合法的文件名,或者是否为路径*/
@SuppressLint("DefaultLocale") private boolean isValidFileOrDir(File file)
{
if (file.isDirectory()) {
return true;
}
else {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".txt")) {
return true;
}
}
return false;
}
private String[] fileToStrArr(List<File> fl)
{
ArrayList<String> fnList = new ArrayList<String>();
for (int i = 0; i < fl.size(); i++) {
String nameString = fl.get(i).getName();
fnList.add(nameString);
}
return fnList.toArray(new String[0]);
}
/*文件列表*/
private List<File> fileNameList;
}
五、总结
1、替换功能尚未完成。
2、细节有待完善,比如推出前判断文件是否已经保存了。
3、打开文件列表部分参考的是开源代码,此部分代码有待深入学习。
4、……有待完善!