Android學(xué)習(xí)之文件存儲(chǔ)讀取
前言
相信大家都知道知道,在AndroidOS中,提供了五中數(shù)據(jù)存儲(chǔ)方式,分別是:ContentProvider存儲(chǔ)、文件存儲(chǔ)、SharedPreference存儲(chǔ)、SQLite數(shù)據(jù)庫存儲(chǔ)、網(wǎng)絡(luò)存儲(chǔ)。那么這一篇,我們介紹文件存儲(chǔ)。
1.Android文件的操作模式
學(xué)過Java的同學(xué)都知道,我們新建文件,然后就可以寫入數(shù)據(jù)了,但是Android卻不一樣,因?yàn)锳ndroid是 基于Linux的,我們?cè)谧x寫文件的時(shí)候,還需加上文件的操作模式,Android中的操作模式如下:
2、文件的操作模式
我們?cè)趯W(xué)Java的時(shí)候都知道,Java中的IO操作來進(jìn)行文件的保存和讀取,Android是基于Linux的,與Java不同的是Android在Context類中封裝好了輸入流和輸出流的獲取方法,分別是: FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),這兩個(gè)方法第一個(gè)參數(shù) 用于指定文件名,第二個(gè)參數(shù)指定打開文件的模式。Android提供的文件模式有:
1.MODE_PRIVATE:Android提供的默認(rèn)操作模式,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問,在該模式下,寫入的內(nèi)容會(huì)覆蓋原文件的內(nèi)容。
2.MODE_APPEND:模式會(huì)檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件。
3.MODE_WORLD_READABLE:表示當(dāng)前文件可以被其他應(yīng)用讀?。?/p>
4.MODE_WORLD_WRITEABLE:表示當(dāng)前文件可以被其他應(yīng)用寫入。
此外,Android還提供了其它幾個(gè)重要的文件操作的方法:
1.getDir(String name , int mode):在應(yīng)用程序的數(shù)據(jù)文件夾下獲取或者創(chuàng)建name對(duì)應(yīng)的子目錄
2.File getFilesDir():獲取app的data目錄下的絕對(duì)路徑
3.String[] fileList():返回app的data目錄下數(shù)的全部文件
4.deleteFile(String fileName):刪除app的data目錄下的指定文件
3、讀寫文件
Android的讀寫文件和Java一樣,也是一樣通過IO操作實(shí)現(xiàn),下面我們通過一個(gè)簡(jiǎn)單的例子走一下這個(gè)流程:
布局文件代碼:
<?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" android:padding="16dp"> <EditText android:id="@+id/ed_file_save" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_file_save" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="保存內(nèi)容" /> <Button android:id="@+id/btn_file_read" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="讀取內(nèi)容" /> <TextView android:id="@+id/tv_read_file" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textColor="#000" android:textSize="14sp" /> </LinearLayout>
Activity代碼:
package com.example.datasave; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /** * Created by Devin on 2016/7/19. */ public class FileDataActivity extends AppCompatActivity { private EditText ed_file_save; private Button btn_file_save; private Button btn_file_read; private TextView tv_read_file; private String fileName = " hello.txt"; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file); ed_file_save = (EditText) findViewById(R.id.ed_file_save); btn_file_save = (Button) findViewById(R.id.btn_file_save); btn_file_read = (Button) findViewById(R.id.btn_file_read); tv_read_file = (TextView) findViewById(R.id.tv_read_file); btn_file_save.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String fileContent = ed_file_save.getText().toString(); try { save(fileContent); ToastUtils.showToast(FileDataActivity.this, "文件寫入成功"); } catch (Exception e) { e.printStackTrace(); ToastUtils.showToast(FileDataActivity.this, "文件寫入失敗"); } } }); btn_file_read.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { String content = read(); tv_read_file.setText("文件的內(nèi)容是:" + content); } catch (IOException e) { e.printStackTrace(); ToastUtils.showToast(FileDataActivity.this, "讀取文件失敗!"); } } }); } public void save(String fileContent) throws Exception { FileOutputStream output = this.openFileOutput(fileName, Context.MODE_PRIVATE); output.write(fileContent.getBytes()); output.close(); } public String read() throws IOException { //打開文件輸入流 FileInputStream input = this.openFileInput(fileName); byte[] temp = new byte[1024]; StringBuffer stringBuffer = new StringBuffer(""); int len = 0; while ((len = input.read(temp)) > 0) { stringBuffer.append(new String(temp, 0, len)); } //關(guān)閉輸入流 input.close(); return stringBuffer.toString(); } }
最后是實(shí)現(xiàn)效果圖:
這里文件使用的模式是私有模式,只能本應(yīng)用讀取還會(huì)覆蓋原文件,這樣就可以實(shí)現(xiàn)簡(jiǎn)單的文件讀寫。
4、讀寫SDcard的文件
讀寫SDCard需要權(quán)限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
對(duì)設(shè)備讀寫SDCard的時(shí)候需要判斷SDCard是否存在,很多手機(jī)是不存在SDcard的,下面我們對(duì)SDCard的讀寫中會(huì)有體現(xiàn),下面我們一起通過例子實(shí)現(xiàn)SDCard的讀寫操作
首先是布局文件代碼:
<EditText android:id="@+id/ed_file_save_sd" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" /> <Button android:id="@+id/btn_file_save_sd" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="寫入到SDcard" /> <Button android:id="@+id/btn_file_read_sd" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="從SDcard讀取" /> <TextView android:id="@+id/tv_read_file_sd" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textColor="#000" android:textSize="14sp" />
Activity代碼:
ed_file_save_sd = (EditText) findViewById(R.id.ed_file_save_sd); tv_read_file_sd = (TextView) findViewById(R.id.tv_read_file_sd); btn_file_read_sd = (Button) findViewById(R.id.btn_file_read_sd); btn_file_read_sd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { String content = readFromSD(); tv_read_file_sd.setText("從SDCard讀取到的內(nèi)容是:" + content); } catch (Exception e) { e.printStackTrace(); ToastUtils.showToast(FileDataActivity.this, "讀取文件失敗!"); } } }); btn_file_save_sd = (Button) findViewById(R.id.btn_file_save_sd); btn_file_save_sd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String content = ed_file_save_sd.getText().toString(); try { save2SDCard(content); ToastUtils.showToast(FileDataActivity.this, "文件寫入SDCard成功"); } catch (Exception e) { e.printStackTrace(); ToastUtils.showToast(FileDataActivity.this, "文件寫入SDCard失敗"); } } }); public void save2SDCard(String content) throws Exception { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 String fileName3 = Environment.getExternalStorageDirectory().getCanonicalPath() + File.separator + "test" + File.separator + fileName2; File file = new File(fileName3); if (!file.getParentFile().exists()) { file.getParentFile().mkdir(); } FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(content.getBytes()); fileOutputStream.close(); } else { ToastUtils.showToast(this, "SDCard不存在"); } } public String readFromSD() throws Exception { StringBuffer stringBuffer = new StringBuffer(""); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String fileName3 = Environment.getExternalStorageDirectory().getCanonicalPath() + File.separator + "test" + File.separator + fileName2; File file = new File(fileName3); if (!file.getParentFile().exists()) { file.getParentFile().mkdir(); } FileInputStream fileInputStream = new FileInputStream(file); byte[] temp = new byte[1024]; int len = 0; while ((len = fileInputStream.read(temp)) > 0) { stringBuffer.append(new String(temp, 0, len)); } fileInputStream.close(); } else { ToastUtils.showToast(this, "SDCard不存在"); } return stringBuffer.toString(); }
SDCard的讀取和文件操作差不多,需要判斷SDCard是否存在,最后是效果圖:
5、讀取raw和assets文件的數(shù)據(jù)
raw/res中的文件會(huì)被映射到Android的R文件中,我們直接通過R文件就可以訪問,這里就不在過多介紹了。
assets中的文件不會(huì)像raw/res中的文件一樣被映射到R文件中,可以有目錄結(jié)構(gòu),Android提供了一個(gè)訪問assets文件的AssetManager對(duì)象,我們?cè)L問也很簡(jiǎn)單:
AssetManager assetsManager = getAssets(); InputStream inputStream = assetsManager.open("fileName");
這樣就可以直接獲取到assets目錄下的資源文件。
AndroidOS的文件存儲(chǔ)就簡(jiǎn)單介紹到這里,下面提供一些文件存儲(chǔ)的工具方法:
package com.example.datasave.io; import android.content.Context; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; /** * IO流 工具類<br> * 很簡(jiǎn)單,僅支持文本操作 */ public class IOUtils { /** * 文本的寫入操作 * * @param filePath 文件路徑。一定要加上文件名字 <br> * 例如:../a/a.txt * @param content 寫入內(nèi)容 * @param append 是否追加 */ public static void write(String filePath, String content, boolean append) { BufferedWriter bufw = null; try { bufw = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(filePath, append))); bufw.write(content); } catch (Exception e1) { e1.printStackTrace(); } finally { if (bufw != null) { try { bufw.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 文本的讀取操作 * * @param path 文件路徑,一定要加上文件名字<br> * 例如:../a/a.txt * @return */ public static String read(String path) { BufferedReader bufr = null; try { bufr = new BufferedReader(new InputStreamReader( new FileInputStream(path))); StringBuffer sb = new StringBuffer(); String str = null; while ((str = bufr.readLine()) != null) { sb.append(str); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (bufr != null) { try { bufr.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * 文本的讀取操作 * * @param is 輸入流 * @return */ public static String read(InputStream is) { BufferedReader bufr = null; try { bufr = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String str = null; while ((str = bufr.readLine()) != null) { sb.append(str); } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (bufr != null) { try { bufr.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } /** * @param context 上下文 * @param fileName 文件名 * @return 字節(jié)數(shù)組 */ public static byte[] readBytes(Context context, String fileName) { FileInputStream fin = null; byte[] buffer = null; try { fin = context.openFileInput(fileName); int length = fin.available(); buffer = new byte[length]; fin.read(buffer); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fin != null) { fin.close(); fin = null; } } catch (IOException e) { e.printStackTrace(); } } return buffer; } /** * 快速讀取程序應(yīng)用包下的文件內(nèi)容 * * @param context 上下文 * @param filename 文件名稱 * @return 文件內(nèi)容 * @throws IOException */ public static String read(Context context, String filename) throws IOException { FileInputStream inStream = context.openFileInput(filename); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outStream.write(buffer, 0, len); } byte[] data = outStream.toByteArray(); return new String(data); } }
好的,關(guān)于Android的數(shù)據(jù)存儲(chǔ)與訪問的文件讀寫就到這里,如果在學(xué)習(xí)本文中遇到什么問題,或者覺得有些紕漏的地方,歡迎提出,萬分感激,謝謝~
- 詳解Android數(shù)據(jù)存儲(chǔ)之Android 6.0運(yùn)行時(shí)權(quán)限下文件存儲(chǔ)的思考
- Android實(shí)現(xiàn)文件存儲(chǔ)并讀取的示例代碼
- android數(shù)據(jù)存儲(chǔ)之文件存儲(chǔ)方法
- android開發(fā)基礎(chǔ)教程—文件存儲(chǔ)功能實(shí)現(xiàn)
- Android圖片添加水印圖片并把圖片保存到文件存儲(chǔ)的實(shí)現(xiàn)代碼
- 實(shí)例詳解Android文件存儲(chǔ)數(shù)據(jù)方式
- 詳解Android開發(fā)數(shù)據(jù)持久化之文件存儲(chǔ)(附源碼)
- 詳解Android文件存儲(chǔ)
- Android編程之SharedPreferences文件存儲(chǔ)操作實(shí)例分析
- Android開發(fā)文件存儲(chǔ)實(shí)例
相關(guān)文章
Android中Xposed框架篇---修改系統(tǒng)位置信息實(shí)現(xiàn)自身隱藏功能實(shí)例
本篇文章介紹了Android中Xposed框架的使用,詳細(xì)的介紹了修改系統(tǒng)位置信息實(shí)現(xiàn)自身隱藏功能實(shí)例,有需要的朋友可以了解一下。2016-11-11Android實(shí)現(xiàn)長(zhǎng)按圓環(huán)動(dòng)畫View效果的思路代碼
這篇文章主要介紹了Android實(shí)現(xiàn)長(zhǎng)按圓環(huán)動(dòng)畫View效果,本文給大家分享實(shí)現(xiàn)思路,通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09android實(shí)現(xiàn)簡(jiǎn)單進(jìn)度條ProgressBar效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)簡(jiǎn)單進(jìn)度條ProgressBar效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07如何設(shè)置Android studio 3.0顯示光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo)
這篇文章主要介紹了如何設(shè)置Android studio 3.0顯示光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo) 很多朋友反映剛升級(jí)了Android studio 3.0,發(fā)現(xiàn)光標(biāo)返回上一次瀏覽位置的箭頭圖標(biāo)沒有了,下文給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-11-11Android編程雙重單選對(duì)話框布局實(shí)現(xiàn)與事件監(jiān)聽方法示例
這篇文章主要介紹了Android編程雙重單選對(duì)話框布局實(shí)現(xiàn)與事件監(jiān)聽方法,涉及Android雙重單選對(duì)話框的界面布局與事件監(jiān)聽、響應(yīng)等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10Android開發(fā)之TextView使用intent傳遞信息,實(shí)現(xiàn)注冊(cè)界面功能示例
這篇文章主要介紹了Android開發(fā)之TextView使用intent傳遞信息,實(shí)現(xiàn)注冊(cè)界面功能,涉及Android使用intent傳值及界面布局等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04Android手機(jī)衛(wèi)士之設(shè)置密碼對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android手機(jī)衛(wèi)士之設(shè)置密碼對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10