对于下方评论的朋友说声道歉,由于只是2017随手写的博客,最后没时间使用博客,所以不知道有朋友关注。抱歉。

  提示:这个是2017年写的,读取文件流效率很低(可能导致程序奔溃),建议使用比较小(最好几十kb)的txt文件进行测试。
  使用工具: eclipse + Android adt
  SDK依赖:4.0.3(也就是android-15)
  包依赖: android-support-v7-appcompat (所以也需要导入这个包)

  本程序只是使用了一些基本的知识点编写了一个比较简单粗陋的txt文本阅读器,效率不高,只适合新手练习。所以大神勿喷。

  其实想到编写这种程序源自本人之前喜欢看小说,而很多小说更新太慢,所以本人就只能找一个完本的.txt小说下载下来,有没有网络都可以看,当然现在不看那玩意了。

  废话就不说了,程序中使用到的有4个类,5个xml文件,其中3个布局文件、String.xml、AndroidManifest.xml。

  先看效果图吧(虽然很丑):

     

  下面就上代码吧,本人都注释好了,由于本人技术还不行,注释不对的,望指正,谢谢>~<

  MainActivity.java:

package cn.hmxin.readbookproject;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast; public class MainActivity extends ActionBarActivity { private ListView bookList = null ;//显示图书(txt)列表组件
private Button btnAdd = null ;//追加书按钮组件
private ArrayAdapter<String> adapter = null ;//适配器
private List<String> data = null ; //用于存储数据,加载到适配器中
private List<String> pathData = null ;//记录路径
private static final int REMOVE_BOOK = Menu.FIRST;//移除书上下文菜单标识
//程序中要使用到的路径
public static final String MYPATH = Environment.getExternalStorageDirectory().getPath() + File.separator + "myBook";
private int longClickPosition = 0 ; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bookList = (ListView)findViewById(R.id.book_list);//绑定组件
btnAdd = (Button)findViewById(R.id.btn_add);//绑定组件 createOrRead();//创建或读取文件方法,顺带显示数据 registerForContextMenu(bookList);//为txt列表组件注册上下文菜单 btnAdd.setOnClickListener(new OnClick());//添加图书按钮的单击监听处理
bookList.setOnItemClickListener(new OnItemClick());//图书列表的子项单击监听处理
bookList.setOnItemLongClickListener(new OnItemLongClick());//图书列表的子项单击监听处理 } //文件的创建和读取
public void createOrRead(){
File dirFile = new File(MYPATH);//声明并实例化一个File类,路径为MYPATH(路径详细看上面)
if(!dirFile.exists()){//如果文件夹不存在
dirFile.mkdirs();//创建文件夹
}
File file = new File(dirFile,"bookPath.txt");//声明并实例化一个File类,父路径为dirFile,文件名为bookPath.txt
if(!file.exists()){//如果文件不存在
try {
file.createNewFile();//创建文件
} catch (IOException e) {
e.printStackTrace();
}
}else{//如果文件已经存在
try {
FileReader fr = new FileReader(file);//声明并实例化FileReader类,路径为file
BufferedReader br = new BufferedReader(fr);//声明并实例化BufferedFile类,缓冲读取数据
data = new ArrayList<String>();//实例化List类,用于添加数据,加载在适配器中
pathData = new ArrayList<String>();//记录路径
String line = "" ;//用于存储读取到的数据 while((line = br.readLine()) != null){//如果还有下一行数据
int sub = line.lastIndexOf(File.separator);//截取文件名使用
String strName = line.substring(sub+1, line.length());//截取到文件名
data.add(strName);//添加文件名
pathData.add(line);//添加整个文件路径
}
br.close();//关闭BufferedReader类
fr.close();//关闭FileReader类
//加载数据在适配器
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, data);
bookList.setAdapter(adapter);//设置适配器
} catch (FileNotFoundException e) {//抛出异常
e.printStackTrace();
} catch (IOException e) {//抛出异常
e.printStackTrace();
}
}
} //用来监听图书列表的选项单击事件
private class OnItemClick implements AdapterView.OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(MainActivity.this, ReadBookActivity.class);//用于跳转Activity使用,此处跳转到读取图书界面
intent.putExtra("txtFilePath", pathData.get(position));//传送要打开的txt文件路径
startActivity(intent);//跳转界面
} }
//用来监听图书列表的选项长按事件
private class OnItemLongClick implements AdapterView.OnItemLongClickListener{
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickPosition = position;//记录长按了列表哪个子项
return false;
}
} //用来监听添加图书按钮的单击事件
private class OnClick implements View.OnClickListener{
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, FileBrowserActivity.class);//跳转到文件浏览选择界面
startActivity(intent);//跳转界面
} } //创建上下文菜单
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
menu.add(0, REMOVE_BOOK, 0, "移除读书");//添加菜单子项
super.onCreateContextMenu(menu, v, menuInfo);
} @Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getItemId() == REMOVE_BOOK){//移除图书处理
removeBook();
}
return super.onContextItemSelected(item);
} //移除图书处理
public void removeBook(){
try {
data.remove(longClickPosition);//移除该项
pathData.remove(longClickPosition);//移除该项
FileWriter fw = new FileWriter(new File(MYPATH + File.separator + "bookPath.txt"));//设置读取文件
BufferedWriter bw = new BufferedWriter(fw);//用BufferedWriter类写入数据
for(String str : pathData){//遍历pathData对象
bw.write(str);//写入数据
bw.newLine();//新的一行
}
bw.close();
//加载数据在适配器
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, data);
bookList.setAdapter(adapter);//设置适配器
} catch (IOException e) {//抛出异常
e.printStackTrace();
}
} }

activity_mai.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.hmxin.readbookproject.MainActivity" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18dip"
android:textStyle="bold"
android:layout_weight="1"
android:text="@string/list_title" /> <Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add"/>
</LinearLayout> <ListView
android:id="@+id/book_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"> </ListView> </LinearLayout>

SubFile.java

package cn.hmxin.readbookproject;
import java.io.File; public class SubFile { private File file =null ;//封装一个File类,用于接收传进构造方法中的File类 public SubFile(File file) {//构造方法
this.file = file ;//本类中的file赋值为传进来的file
} public File getFile() {//getter方法,返回File类
return this.file;//返回本类中的file对象
} @Override
public String toString() {
String str = null; //声明一个字符串用来返回值
if(file.isDirectory()) {//是文件夹
str = "[文件夹]" + file.getName();
}else {//是文件
if(file.getName().lastIndexOf(".txt")>-1) {//这里是过滤掉别的文件,做文件浏览器,可以去掉
str = "[文件]" + file.getName();//赋值"[文件]"+文件名字
}
}
return str;//返回该字符串
}
}

FileBrowserActivity.java

package cn.hmxin.readbookproject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast; public class FileBrowserActivity extends Activity { private ListView fileList = null ;//显示文件的列表
private ArrayAdapter adapter = null ;//适配器 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.file_browser_layout);
setTitle("选择您的文件名");//更改标题
fileList = (ListView)findViewById(R.id.file_list);//绑定组件
openFile(adapter, fileList);//打开文件和配置适配器,显示在列表上 fileList.setOnItemClickListener(new OnItemClick());//文件列表的子项单击监听处理 } /**
* 此方法用于装载数据
* @param adapter ArrayAdapter适配器
* @param list 要显示的ListView
*/
public void openFile(ArrayAdapter adapter, ListView list){
List<SubFile> ndata = new ArrayList<SubFile>();//用于存放文件名,加载到适配器中
String strPath = getIntent().getStringExtra("filename");//获取上个界面传来的值
if(strPath == null){//没有有数据
strPath = Environment.getExternalStorageDirectory().getPath();//根目录
}
File pathFile = new File(strPath);//要显示的目录
if(pathFile != null){//有这个目录
File[] files = pathFile.listFiles();//获取目录下的所有文件夹与文件
for(File file : files){//全部遍历
if(new SubFile(file).toString()!=null){//如果不是筛选掉的文件
ndata.add(new SubFile(file));//添加到mdata对象中
}
}
//配置适配器
adapter = new ArrayAdapter(FileBrowserActivity.this, android.R.layout.simple_list_item_1, ndata);
list.setAdapter(adapter);//设置列表的适配去
}else{//空文件处理
Toast.makeText(FileBrowserActivity.this , "查找文件为空!", Toast.LENGTH_SHORT).show();
}
} //文件列表子项的单击监听处理
private class OnItemClick implements AdapterView.OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SubFile subFile = (SubFile) parent.getAdapter().getItem(position);//获取子项存储的SubFile类,该类可以获取到子项所在路径
String filename = subFile.getFile().getPath();//filename赋值为subFile对象中的路径
Intent intent = null;//声明Intent类,用于跳转界面
if(subFile.getFile().isDirectory()){//如果路径为文件夹
intent = new Intent(FileBrowserActivity.this, FileBrowserActivity.class);//还是跳转到改Activity
intent.putExtra("filename", filename);//传入路径
}else{//文件的话
intent = new Intent(FileBrowserActivity.this, MainActivity.class);//跳转到主界面
writeData(filename);//调用writeData方法,该方法用于写入数据
}
startActivity(intent);//跳转界面
finish();//清除界面
} } /**
* 该方法用于写入数据
* @param str 要写入的值
*/ public void writeData(String str){
File file = new File(MainActivity.MYPATH+File.separator+"bookPath.txt");//要操作的文件
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(file,true));//用BufferedWriter类追加写入数据
bw.append(str);//追加数据
bw.newLine();//新的一行
bw.close();//关闭BufferedWrite类
} catch (IOException e) {//抛出异常
e.printStackTrace();
}
} }

file_browser_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18dip"
android:textStyle="bold"
android:text="@string/file_select_title" /> <ListView
android:id="@+id/file_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView> </LinearLayout>

ReadBookActivity.java

package cn.hmxin.readbookproject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast; public class ReadBookActivity extends Activity { private TextView bookContent = null ;//显示文本的组件 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.read_book_layout); bookContent = (TextView)findViewById(R.id.book_content);//绑定文本组件
bookContent.setMovementMethod(ScrollingMovementMethod.getInstance());//给文本组件加入滚动条 String txtFilePath = getIntent().getStringExtra("txtFilePath");//获取传进来的文本路径
if(txtFilePath != null){//如果有传进数据
int index = txtFilePath.lastIndexOf(File.separator);//用来截取文本的名字的第一个参数
String name = txtFilePath.substring(index+1, txtFilePath.length());//截取文本名字
setTitle(name);//设置标题为文本名字
try {
FileInputStream fr = new FileInputStream(txtFilePath);//文件输出流
BufferedReader br = new BufferedReader(new InputStreamReader(fr, "utf-8"));//缓冲读取文件数据
String line = "" ;//记录每一行数据
String content = "" ;
while((line = br.readLine()) != null){//如果还有下一行数据
content += line + "\n" ;
}
bookContent.setText(content);;//追加显示数据
br.close();//关闭文件输出流
fr.close();//关闭缓冲区
} catch (IOException e) {//抛出异常
Toast.makeText(ReadBookActivity.this, "没有此文件!", Toast.LENGTH_SHORT).show();//提示异常
finish();//直接关闭界面
}
}
}
}

read_book_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/book_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="14dip"/>
</LinearLayout>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">图书阅读程序(txt)</string>
<string name="list_title">图书列表:</string>
<string name="add">添加图书</string>
<string name="file_select_title">请选择.txt文件:</string> </resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.hmxin.readbookproject"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ReadBookActivity"> </activity>
<activity android:name=".FileBrowserActivity"> </activity>
</application> </manifest>

  最后想说的是,新手们可以着重看SubFile.java和FileBrowserActivity.java这两个文件,这两个文件实现的是一个文件浏览器,方法简单至极,是本人在看教程中学到的。到最后你要是想做界面漂亮的浏览器,也可以借鉴借鉴。

  源码链接:https://files.cnblogs.com/files/hmxin/ReadBookProject.zip

《黑幕下的人》

Android简单的编写一个txt阅读器(没有处理字符编码),适用于新手学习的更多相关文章

  1. CSharpGL(34)以从零编写一个KleinBottle渲染器为例学习如何使用CSharpGL

    CSharpGL(34)以从零编写一个KleinBottle渲染器为例学习如何使用CSharpGL +BIT祝威+悄悄在此留下版了个权的信息说: 开始 本文用step by step的方式,讲述如何使 ...

  2. 如何编写一个JSON解析器

    编写一个JSON解析器实际上就是一个函数,它的输入是一个表示JSON的字符串,输出是结构化的对应到语言本身的数据结构. 和XML相比,JSON本身结构非常简单,并且仅有几种数据类型,以Java为例,对 ...

  3. 从零开始编写一个BitTorrent下载器

    从零开始编写一个BitTorrent下载器 BT协议 简介 BT协议Bit Torrent(BT)是一种通信协议,又是一种应用程序,广泛用于对等网络通信(P2P).曾经风靡一时,由于它引起了巨大的流量 ...

  4. Android 从零编写一个带标签 TagTextView

    最近公司的项目升级到了 9.x,随之而来的就是一大波的更新,其中有个比较明显的改变就是很多板块都出了一个带标签的设计图,如下: 怎么实现 看到这个,大多数小伙伴都能想到这就是一个简单的图文混排,不由得 ...

  5. python简介、第一个python程序、变量、字符编码、用户交互程序、if...else、while、for

    也愿大家永葆初心-- 已识乾坤大,犹怜草木青. 一.python简介 首先,我们普及一下编程语言的基础知识.用任何编程语言来开发程序,都是为了让计算机干活,比如下载一个MP3,编写一个文档等等,而计算 ...

  6. Python学习笔记一:第一个Python程序,变量,字符编码与二进制,用户交互程序

    第一个python程序 Windows:设置环境变量,X:\pthonxxx,xxx是版本号 在命令提示符下 输入python,进入解释器 >>>print(“Hello World ...

  7. 【Android自动化】编写一个log模块,输出至控制台,供程序运行查看

    # -*- coding:utf-8 -*- import logging def get_log(name): log = logging.getLogger(name) log.setLevel( ...

  8. 项目:Android平台txt阅读软件

    项目:Android平台txt阅读软件 项目组成员:20145107李长达.20145110屠轶成.20145120黄玄曦.20145122程智崟 Need: 从古至今,阅读都是人类生活中的一大部分, ...

  9. (android高仿系列)今日头条 --新闻阅读器 (二)

    高仿今日头条 --- 第一篇:(android高仿系列)今日头条 --新闻阅读器 (一)    上次,已经完毕了头部新闻分类栏目的拖动效果. 这篇文章是继续去完好APP 今日头条  这个新闻阅读器的其 ...

随机推荐

  1. 删除List中指定的元素

    删除List中指定的元素 CopyOnWriteArrayList是ArrayList的一个线程安全的变体实现,即可在多线程并发环境中使用 List<Map<String, Object& ...

  2. C# Request获取URL常见用法

    如果测试的url地址是http://www.test.com/testweb/default.aspx, 结果如下: Request.ApplicationPath: /testweb Request ...

  3. 【Leetcode】【Medium】Divide Two Integers

    Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...

  4. 【Leetcode】【Medium】Multiply Strings

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  5. ppt中调整图片位置

    按方向键时,如果调整的位置过大,可以使用 Ctrl + 方向键.

  6. node-7.2.1 already installed, it's just not linked

    直接在terminal下运行以卸载node和nvm: sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,shar ...

  7. sql2005 和 mysql 定时备份批处理

    保存为sqlbak.bat  目录我直接放winrar 的根目录了 或者拷贝一个winrar.exe 具体目录随意. 然后添加计划任务个人的话建议一周或者一天 虚拟主机等 建议每周或者每月 @echo ...

  8. HTTP 中状态码 302的使用场景

    一直都知道302是临时重定向,可是不懂为什么要用这个,直到看到了这个 这样就可以用一个URL,来访问其他的URL上的资源了,非常的nice

  9. 编程三基:cpu:算法,总线(io):一切皆文件;内存:运行空间

    编程三基:cpu:算法,总线:一切皆文件:内存:数据.运行空间 原文找不到了.

  10. mxnet导入图像数据

    图像的标签在一个json文件中. %matplotlib inline import json import gluonbook as gb import mxnet as mx from mxnet ...