现在的位置: 首页 > 综合 > 正文

从SDCard中读取文本内容

2013年10月16日 ⁄ 综合 ⁄ 共 5845字 ⁄ 字号 评论关闭

        这是一个把记事本中的内容读取到内存中并将内容显示在屏幕上的demo。在这个demo中,整个程序的流程是这样:

        step 1:首先在程序的assets文件夹下存放一个test.txt文件,文件是utf-8编码格式,里面存放的是一篇文章。windows下生成的记事本默认是ANSI编码格式,你只需要点击 文件 --> 另存为 --> 在弹出框中把编码格式改成utf-8 --> 保存覆盖原文件即可。

        step 2:检测sdcard是否插入,false则输出提示:"sdcard未插入。",true则执行step3。

        step 3:检测sdcard中mana文件夹下是否有test.txt文件,如果有则读取文件内容,如果没有则从assets中把test.txt文件拷贝到sdcard的mana文件夹下,然后读取sdcard中的test.txt文件内容。

        step 4:把文件内容显示到设备屏幕上大功告成。

        显示效果如下:

       

       

这个是布局main.xml的内容,只有一个textView,在textView外层包了一个scrollView,使得当文字多于屏幕能够显示的能力时可以拖动文字。

<RelativeLayout 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" >

    <ScrollView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
       	<TextView
	        android:id="@id/text_content"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"/>
    </ScrollView>


</RelativeLayout>

Main.class,这是显示的Activity,其中最关键的是对MappedByteBuffer类的掌握。

/**
 * 从SDCard中读取文本内容
 * @author haozi
 *
 */
public class Main extends Activity {

	public static final String SDCARD_FILEDIR_PATH = "sdcard/mana/";
	private TextView textContent;                                          // 在这个控件中显示文本信息
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        this.textContent = (TextView) this.findViewById(R.id.text_content);
        
        String content = getTextContent("test.txt");
        this.textContent.setText(content);
    }
    
    /**
     * 得到文本中的内容
     * @param textFilePath 文本文件在assets下的相对路径
     * @return
     */
    private String getTextContent(String textFilePath){
    	
    	String content = "";
    	
    	// 检测SDCard是否插入
    	if(SDCardUtil.checkSDCARD()){
    		
    		// 1 获取文件
    		File tempFile = null;
    		// 检测文件是否存在
    		if(SDCardUtil.checkFileExist(SDCARD_FILEDIR_PATH, "test.txt")){// 文件存在,则获取这个文件
    			// 查找目录下所有后缀名为txt的文件。
    			File[] files = SDCardUtil.findSDCardFile("sdcard/mana/", "txt");
    			if(files != null && files.length > 0){
        			for(int i=0; i<files.length; i++){
        				if("test.txt".equals(files[i].getName())){
        					tempFile = files[i];
        				}
        			}
    			}
    		}else{// 文件不存在,则创造这个文件
    			tempFile = SDCardUtil.createFile2SDCard(SDCARD_FILEDIR_PATH, "test.txt");
    			// 从assets中复制文件到sdcard中。
    			if(AssetsUtil.isAssetExistent(Main.this, textFilePath)){
    				InputStream is = AssetsUtil.openAssetPostion(Main.this, textFilePath);
    				try {
						FileUtils.copyInputStreamToFile(is, tempFile);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
    			}
    		}
    		
    		// 2 读取文本到MappedByteBuffer中
    		// MappedByteBuffer 将文件直接映射到内存(这里的内存指的是虚拟内存,并不是物理内存,后面说证明这一点)。
    		// 通常,可以映射整个文件,如果文件比较大的话可以分段进行映射,只要指定文件的那个部分就可以。而且,与ByteBuffer十分类似,
    		// 没有构造函数(你不可new MappedByteBuffer()来构造一个MappedByteBuffer),我们可以通过 java.nio.channels.FileChannel 的 map() 方法来获取 MappedByteBuffer 。
    		// 其实说的通俗一点就是Map把文件的内容被映像到计算机虚拟内存的一块区域,这样就可以直接操作内存当中的数据而无需操作的时候每次都通过I/O去物理硬盘读取文件,所以效率上有很大的提升!
    		// FileChannel提供了map方法来把文件影射为内存映像文件: MappedByteBuffer map(int mode,long position,long size); 
    		// 可以把文件的从position开始的size大小的区域映射为内存映像文件,mode指出了 可访问该内存映像文件的方式
    		MappedByteBuffer buffer = null;
    		long bufferLength = 0;
    		try {
    			RandomAccessFile rFile = new RandomAccessFile(tempFile, "r");
    			bufferLength = rFile.length();
				buffer = rFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, bufferLength);
				byte[] bytes = new byte[(int) bufferLength];
				for(int i=0; i<bytes.length; i++){
					bytes[i] = buffer.get(i);
				}
				content = new String(bytes, "utf-8");
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}else{
    		content = "sdcard没有插入。";
    	}
    	return content;
    }
}

两个类工具,负责对sdcard和assets的检测和文件操作。

AssetsUtil

public class AssetsUtil {

	/**
	 * 判断assets下是否存在某文件(判断完后,会关闭IO流)
	 *
	 * @param assetPath
	 * @return
	 */
	public static boolean isAssetExistent(Context context, String assetPath) {
		InputStream is = null;
		try {
	        is = context.getAssets().open(assetPath);
	        return is != null;
        } catch (IOException e) {
        	return false;
        } finally {
        	try {
	            if(is != null)
	            	is.close();
            } catch (IOException e) {
            }
        }
	}
	
	/**
	 * 判断assets下是否存在某文件,若存在,直接返回IO流,否则返回空
	 *
	 * @param assetPath
	 * @return
	 */
	public static InputStream openAssetPostion(Context context, String assetPath) {
		InputStream is = null;
		try {
			is = context.getAssets().open(assetPath);
			return is;
		} catch (IOException e) {
			return null;
		}
	}
}

SDcardUtil

public class SDCardUtil {

	private static String SDPATH;

	static {
		// 得到当前外部存储设备的目录
		// /SDCARD
		SDPATH = Environment.getExternalStorageDirectory() + "/";
	}

	public static String getSDPATH() {

		return SDPATH;
	}

	/**
	 * 检查SD卡是否插入
	 * 
	 * @return
	 *
	 */
	public static boolean checkSDCARD() {

		String status = Environment.getExternalStorageState();
		
		if (status.equals(Environment.MEDIA_MOUNTED)) {
			return true;
		}

		return false;
	}

	/**
	 * 创建文件到SDCard中
	 * 
	 * @param path
	 * @param fileName
	 * @return true:创建成功 false:创建失败(文件已经存在)
	 * 
	 */
	public static File createFile2SDCard(String path, String fileName) {

		// ///////////////////////////////////////
		// 创建SD卡目录
		// ///////////////////////////////////////
		File dir = new File(path);

		if (!dir.exists()) {
			dir.mkdirs();
		}

		// //////////////////////////////////////////
		// 创建SD卡文件
		// ///////////////////////////////////////////
		File file = new File(path + fileName);

		if (file.exists()) {

			file.delete();
		}
		
		try {
			file.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return file;
	}

	/**
	 * 判断文件是否存在在SDCard卡上
	 * 
	 * @param path
	 * @param fileName
	 * @return
	 */
	public static boolean checkFileExist(String path, String fileName) {

		File file = new File(path + fileName);

		return file.exists();
	}
	
	/**
	 * 查找某目录下所有fileType类型的文件
	 * 
	 * @param path
	 * @param fileType
	 * @return
	 * 
	 */
	public static File[] findSDCardFile(String path, final String fileType) {

		File dir = new File(path);

		if (dir.isDirectory()) {
			File[] files = dir.listFiles(new FilenameFilter() {

				@Override
				public boolean accept(File dir, String filename) {

					return (filename.endsWith(fileType));
				}
			});

			Arrays.sort(files, new Comparator<File>() {
				@Override
				public int compare(File str1, File str2) {

					return str2.getName().compareTo(str1.getName());
				}
			});

			return files;
		}

		return null;
	}
}

当然,对sdcard的操作要记得在AndroidManifest.xml中添加对sdcard操作文件的权限。

 <!-- 在SDCard中创建与删除文件权限 -->
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
 <!-- 往SDCard写入数据权限 -->
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

在这个demo中,我还使用了阿帕奇提供的common项目的一些好用的工具jar包。它们使我在对文件处理操作上省下了不少代码。

【上篇】
【下篇】

抱歉!评论已关闭.