Android SD卡简单的文件读写操作

简介:

最近有这样的需求,把每次统计到的数据,以txt形式保存到手机SD卡或是手机内存中,遇到一些问题,记录下来。


首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.   <!-- SDCard中创建与删除文件权限 -->  
  2.   <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  3.  <!-- 向SDCard写入数据权限 -->  
  4.  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

  接着在使用SDcard进行读写的时候 会用到Environment类下面的几个静态方法  : 

    1: getDataDirectory() 获取到Android中的data数据目录(sd卡中的data文件夹)
    2:getDownloadCacheDirectory() 获取到下载的缓存目录(sd卡中的download文件夹)
    3:getExternalStorageDirectory() 获取到外部存储的目录 一般指SDcard(/storage/sdcard0)
    4:getExternalStorageState() 获取外部设置的当前状态 一般指SDcard,比较常用的应该是 MEDIA_MOUNTED(SDcard存在并且可以进行读写)还有其他的一些状态,可以在文档中进行查找。

    5:getRootDirectory()  获取到Android Root路径


好,以下是具体操作,直接看代码:

1,判断SD卡是否存在

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 判断SDCard是否存在 [当没有外挂SD卡时,内置ROM也被识别为存在sd卡] 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static boolean isSdCardExist() {  
  7.     return Environment.getExternalStorageState().equals(  
  8.             Environment.MEDIA_MOUNTED);  
  9. }  

2,获取SD卡根目录

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 获取SD卡根目录路径 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static String getSdCardPath() {  
  7.     boolean exist = isSdCardExist();  
  8.     String sdpath = "";  
  9.     if (exist) {  
  10.         sdpath = Environment.getExternalStorageDirectory()  
  11.                 .getAbsolutePath();  
  12.     } else {  
  13.         sdpath = "不适用";  
  14.     }  
  15.     return sdpath;  
  16.   
  17. }  

3,获取默认的文件存放路径

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 获取默认的文件路径 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static String getDefaultFilePath() {  
  7.     String filepath = "";  
  8.     File file = new File(Environment.getExternalStorageDirectory(),  
  9.             "abc.txt");  
  10.     if (file.exists()) {  
  11.         filepath = file.getAbsolutePath();  
  12.     } else {  
  13.         filepath = "不适用";  
  14.     }  
  15.     return filepath;  
  16. }  

4-1,使用FileInputStream读取文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. try {  
  2. le file = new File(Environment.getExternalStorageDirectory(),  
  3. "test.txt");  
  4.     FileInputStream is = new FileInputStream(file);  
  5.     byte[] b = new byte[inputStream.available()];  
  6.     is.read(b);  
  7.     String result = new String(b);  
  8.     System.out.println("读取成功:"+result);  
  9. catch (Exception e) {  
  10.     e.printStackTrace();  
  11. }  

4-2,使用BufferReader读取文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.     BufferedReader br = new BufferedReader(new FileReader(file));  
  5.     String readline = "";  
  6.     StringBuffer sb = new StringBuffer();  
  7.     while ((readline = br.readLine()) != null) {  
  8.         System.out.println("readline:" + readline);  
  9.         sb.append(readline);  
  10.     }  
  11.     br.close();  
  12.     System.out.println("读取成功:" + sb.toString());  
  13. catch (Exception e) {  
  14.     e.printStackTrace();  
  15. }  

httpConnection读取流保存成String数据

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. URL url = new URL(getForwardUrl("/queryUserByUNorIP"));  
  2. HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  3. InputStream is = conn.getInputStream();  
  4. BufferedReader br = new BufferedReader(new InputStreamReader(is));  
  5. StringBuilder sb = new StringBuilder();  
  6. String readline = null;  
  7. while ((readline = br.readLine()) != null) {  
  8.     sb.append(readline);  
  9. }  
  10. System.out.println("result"+sb.toString());  
等效于使用ByteArrayOutputStream

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. InputStream is = conn.getInputStream();  
  2. ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  3. byte[] buffer = new byte[1024];  
  4. int len =-1 ;  
  5. while ((len=is.read(buffer))!=-1) {  
  6.     bos.write(buffer, 0, len);  
  7. }  
  8. is.close();  
  9. bos.close();  
  10. String result = new String(bos.toByteArray());  
  11. System.out.println("result"+result);  

5-1,使用FileOutputStream写入文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.         FileOutputStream fos = new FileOutputStream(file);  
  5.         String info = "I am a chinanese!";  
  6.            fos.write(info.getBytes());  
  7.            fos.close();  
  8.     System.out.println("写入成功:");  
  9. catch (Exception e) {  
  10.     e.printStackTrace();  
  11. }  

5-2,使用BufferedWriter写入文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.     //第二个参数意义是说是否以append方式添加内容  
  5.     BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  6.     String info = " hey, yoo,bitch";  
  7.     bw.write(info);  
  8.     bw.flush();  
  9.     System.out.println("写入成功");  
  10. catch (Exception e) {  
  11.     e.printStackTrace();  
  12. }  


读取和写入我们都实现了,貌似很简单的样子,但是我们现在想每隔30秒进行一次数据整理,然后把他们写入到我们制定的txt文件中,但是我想每次都能在上一次的结尾处开始写入,这样在电脑上通过文本打开时,就能看到每一行的数据了。

这其实要求我们每一次写入数据时,都要有换行的操作符号,比如:\n,并且IO读写能以追加的方式写入到文件里。

刚开始我很笨的想到,每次写入前,先把文件读取出来并且生成一个StringBuffer,然后再append,然后再写入.....这种方式导致每次都要2次以上的IO操作,读和写。其实系统写入时就给我们自带了append方式,还是要勤看文档啊!

BufferedWriter

使用BufferedWriter,在构造BufferedWriter时,把第二个参数设为true
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(  
                    new FileOutputStream(file, true)));  
         out.write(conent);  

FileWriter

构造函数中的第二个参数true表示以追加形式写文件  
         FileWriter writer = new FileWriter(fileName, true);  
         writer.write(content);  
         writer.close();

// 打开一个随机访问文件流,按读写方式  
RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");  
// 文件长度,字节数  
long fileLength = randomFile.length();  
// 将写文件指针移到文件尾。  
randomFile.seek(fileLength);  
randomFile.writeBytes(content);  
randomFile.close(); 



问题:我在file写入时,没一次写完后,明明都添加了换行符(bw.write("\n")),为什么在Window的文本文档中看不到换行呢?而在EditPlus或是notepad++中就能看到换行后的效果?

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  2. String info = " hey, yoo,bitch";  
  3. bw.write(info);  
  4. bw.write("\n");  
  5. bw.flush();  

如上代码所示,可是在windows的文本文档中:


但是在诸如notepad++或EditPlus中看到却是没问题的:



这是为什么呢?

这是windows与linux系统的编码模式不同造成的。android系统是linux内核,与windows不同。windows是采用的是DOS编码方式,所用的换行符是DOS换行符CR/LF,也就是我们俗称的\r\n,(如果不理解可以去百度一下转义字符,一般程序员会用到这些知识),而linux系统的换行符为UNIX换行符LF,也就是\n,苹果的MAC系统用的是MAC换行符CR,也就是\r,现在我想你也差不多理解了。你在android手机里建立的文档肯定用的是UNIX换行符,也就是一个\n,但是这个文档你拿到windows里用记事本打开的话,因为windows记事本是DOS换行符\r\n,所以你少了个\r,所以没法识别成换行,只能给你识别成一个小方块了,解决办法很简单,你可以用EditPlus或者UltraEdit软件打开,UltraEdit也能转换这些编码模式,转换成DOS模式就可以了。


所以,我们只需要添加:\r\n  

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  2. String info = " hey, yoo,bitch";  
  3. bw.write(info);  
  4. bw.write("\r\n");  
  5. bw.flush();  

相关文章
|
7月前
|
Android开发 开发者
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
本文详细介绍了如何通过自定义 `attrs.xml` 文件实现 Android 自定义 View 的属性配置。以一个包含 TextView 和 ImageView 的 DemoView 为例,讲解了如何使用自定义属性动态改变文字内容和控制图片显示隐藏。同时,通过设置布尔值和点击事件,实现了图片状态的切换功能。代码中展示了如何在构造函数中解析自定义属性,并通过方法 `setSetting0n` 和 `setbackeguang` 实现功能逻辑的优化与封装。此示例帮助开发者更好地理解自定义 View 的开发流程与 attrs.xml 的实际应用。
213 2
Android自定义View之不得不知道的文件attrs.xml(自定义属性)
|
7月前
|
Java Android开发
Android studio中build.gradle文件简单介绍
本文解析了Android项目中build.gradle文件的作用,包括jcenter仓库配置、模块类型定义、包名设置及依赖管理,涵盖本地、库和远程依赖的区别。
667 19
|
10月前
|
移动开发 安全 Java
Android历史版本与APK文件结构
通过以上内容,您可以全面了解Android的历史版本及其主要特性,同时掌握APK文件的结构和各部分的作用。这些知识对于理解Android应用的开发和发布过程非常重要,也有助于在实际开发中进行高效的应用管理和优化。希望这些内容对您的学习和工作有所帮助。
1054 83
|
7月前
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
1976 2
|
缓存 Android开发 Kotlin
【安卓app开发】kotlin Jetpack Compose框架 | 先用OKhttp下载远程音频文件再使用ExoPlayer播放
使用 Kotlin 的 Jetpack Compose 开发安卓应用时,可以结合 OkHttp 下载远程音频文件和 ExoPlayer 进行播放。在 `build.gradle` 添加相关依赖后,示例代码展示了如何下载音频并用 ExoPlayer 播放。代码包括添加依赖、下载文件、播放文件及简单的 Compose UI。注意,示例未包含完整错误处理和资源释放,实际应用需补充这些内容。
|
存储 Android开发 Kotlin
开发安卓app OKhttp下载后使用MediaPlayer播放
在Android Jetpack Compose应用程序中,要使用OkHttp下载远程音频文件并在本地播放,你需要完成以下几个步骤: 1. **添加依赖**:确保`build.gradle`文件包含OkHttp和Jetpack Compose的相关依赖。 2. **下载逻辑**:创建一个`suspend`函数,使用OkHttp发起网络请求下载音频文件到本地。 3. **播放逻辑**:利用`MediaPlayer`管理音频播放状态。 4. **Compose UI**:构建用户界面,包含下载和播放音频的按钮。
|
Web App开发 Android开发
Android 使用 aria2c + 百度网盘助手下载百度云文件
首先表明,这是一篇我转载的文章 原为知乎专题 :https://zhuanlan.zhihu.com/p/26873167?group_id=846415883457949696 闲的无聊,突然想到自己在 Android 上下百度云的东西很麻烦,而且不想用山寨云什么的,如果能在 Android 也能实现 aria2c + 百度网盘助手的那一套就好了 于是试了一下,那当然是可以的 ( 首先,你去 aria2c 的 github-release** 页面,那里就有 aria2c for Android 的二进制包,都不用自己编译了多好。
2566 0
|
2月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
318 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
290 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡

热门文章

最新文章