HDU-安卓程式開發之簡單儲存/內部儲存/外部儲存 & 捉蟲

fourvolt發表於2020-12-04

前言

大三上學期可以說是各工科學生課最難最多的一學期了,又因下學期大家普遍需要找工作,所以都壓力比較大吧…
安卓作為我本學期選的五門專業課中學的最認真的(因為每週都有佈置作業),所以我對它相對比較瞭解,下面來給大家分享一下【第8章資料儲存與訪問-簡單儲存/內部儲存/外部儲存】的原始碼和心得

介面和原始碼

在這裡插入圖片描述

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fourvolt69.lesson">
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"> </uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> </uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"> </uses-permission>
    //另外,外部儲存因為需要訪問程式資料之外的儲存空間,所以需要在安卓機的設定(app permission->storage)把storage的許可權給到本程式
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    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="fourvolt69.lesson.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView" />

    <Button
        android:text="簡單讀"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button2"
        android:layout_alignBaseline="@+id/button"
        android:layout_alignBottom="@+id/button"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="73dp" />

    <Button
        android:text="簡單寫"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="69dp"
        android:id="@+id/button"
        android:layout_below="@+id/editText3"
        android:layout_toEndOf="@+id/textView" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:ems="10"
        android:layout_marginTop="20dp"
        android:id="@+id/editText3"
        android:layout_below="@+id/editText2"
        android:layout_centerHorizontal="true"
        android:hint="height" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:ems="10"
        android:layout_marginTop="20dp"
        android:id="@+id/editText2"
        android:layout_below="@+id/editText"
        android:layout_alignStart="@+id/editText3"
        android:hint="age" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:ems="10"
        android:layout_marginTop="20dp"
        android:id="@+id/editText"
        android:layout_below="@+id/textView"
        android:layout_alignStart="@+id/editText2"
        android:hint="name" />

    <Button
        android:text="內部讀"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button4"
        android:layout_alignBaseline="@+id/button3"
        android:layout_alignBottom="@+id/button3"
        android:layout_alignStart="@+id/button2" />

    <Button
        android:text="外部讀"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button6"
        android:layout_alignBaseline="@+id/button5"
        android:layout_alignBottom="@+id/button5"
        android:layout_alignStart="@+id/button4" />

    <Button
        android:text="外部寫"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button5"
        android:layout_marginTop="15dp"
        android:layout_below="@+id/button3"
        android:layout_alignStart="@+id/button3" />

    <Button
        android:text="內部寫"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:id="@+id/button3"
        android:layout_below="@+id/button"
        android:layout_alignStart="@+id/button" />
</RelativeLayout>

MainActivity.java

package fourvolt69.lesson;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.os.Environment;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    EditText nameText, ageText, heightText;
    SharedPreferences sharedPreferences;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final String tag="sdCardReadWrite";
        setContentView(R.layout.activity_main);
        nameText = (EditText) findViewById(R.id.editText);
        ageText = (EditText) findViewById(R.id.editText2);
        heightText = (EditText) findViewById(R.id.editText3);
        Button shSave = (Button) findViewById(R.id.button);
        Button shRead = (Button) findViewById(R.id.button2);
        Button inSave = (Button) findViewById(R.id.button3);
        Button inRead = (Button) findViewById(R.id.button4);
        Button sdSave = (Button) findViewById(R.id.button5);
        Button sdRead = (Button) findViewById(R.id.button6);
        /*
        簡單儲存
        sharedPreferences = getSharedPreferences("sp1",MODE_PRIVATE);
        shSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SharedPreferences.Editor editor=sharedPreferences.edit();
                editor.putString("name",nameText.getText().toString());
                editor.putInt("age",Integer.valueOf(ageText.getText().toString()));
                editor.putFloat("height",Float.valueOf(heightText.getText().toString()));
                editor.commit();
            }
        });
        shRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String name=sharedPreferences.getString("name","杭電學生");
                int age=sharedPreferences.getInt("age",20);
                float height=sharedPreferences.getFloat("height",1.70F);
                nameText.setText(name);
                ageText.setText(String.valueOf(age));
                heightText.setText(String.valueOf(height));
            }
        });
         */
        /*
        內部儲存
        inSave.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view){
                String text = nameText.getText().toString();
                FileOutputStream fos = null;
                try {
                    fos = openFileOutput("myName", Context.MODE_APPEND);
                    try{
                        fos.write(text.getBytes());
                        fos.flush();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }catch (FileNotFoundException e){
                    e.printStackTrace();
                }finally {
                    try{
                        fos.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        });
        inRead.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view){
                FileInputStream fis=null;
                try {
                    fis=openFileInput("myName");
                    try{
                        byte[] readBytes=new byte[fis.available()];
                        while (fis.read(readBytes)!=-1){

                        }
                        String s = new String(readBytes);
                        nameText.setText(s);
                    } catch (IOException e){
                        e.printStackTrace();
                    }
                }catch (FileNotFoundException e){
                    e.printStackTrace();
                }finally {
                    try{
                        fis.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        });
        */
        sdSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                File dir = new File(Environment.getExternalStorageDirectory().toString());
                if(dir.exists()&&dir.canWrite()){
                    Log.d(tag,"該目錄存在 且 可寫");
                    File newFile = new File(Environment.getExternalStorageDirectory(),"myName2.txt");
                    FileOutputStream fos = null;
                    try{
                        newFile.createNewFile();
                        fos = new FileOutputStream(newFile);
                        fos.write(nameText.getText().toString().getBytes());
                        fos.flush();
                        Log.d(tag,"成功寫入");
                    }catch (IOException e){
                        e.printStackTrace();
                    }finally {
                        try{
                            fos.close();
                            Log.d(tag,"關閉fos");
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                }
                else {
                    Log.d(tag,"該目錄不存在 或 不可寫");
                }
            }
        });
        sdRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                File dir1 = new File(Environment.getExternalStorageDirectory(),"myName2.txt");
                if(dir1.exists()&&dir1.canRead()){
                    Log.d(tag,"該目錄存在 且 可讀");
                    FileInputStream fis = null;
                    try{
                        fis = new FileInputStream(dir1);

                        try {
                            byte[] readBytes = new byte[fis.available()];
                            while (fis.read(readBytes)!=-1){

                            }
                            String s = new String(readBytes);
                            nameText.setText(s);
                            Log.d(tag,"讀取成功");
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }catch (IOException e){
                        e.printStackTrace();
                    }finally {
                        try{
                            fis.close();
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                }
                else{
                    Log.d(tag,"該目錄不存在 或 不可讀");
                }
            }
        });
    }
    @Override
    protected void onStop() {
        super.onStop();
    }
}

心得

此三塊內容課時為3 * 45分鐘,總的來說簡單儲存和內部儲存算是比較簡單的,我也沒有遇到什麼麻煩,而外部儲存則比較苦惱,下面列舉一些容易忽略的知識點和容易觸發的小bug

  1. try & catch
//openFileOutput函式
String FILE_NAME = "fileDemo.txt";
FileOutputStream fos = openFileOutput(FILE_NAME,Context.MODE_PRIVATE)
String text = “Some data”;
fos.write(text.getBytes());
fos.flush();
fos.close();
//openFileInput()函式
String FILE_NAME = "fileDemo.txt";
FileInputStream fis = openFileInput(FILE_NAME);
//fis.available():fis的有效位元組數
byte[] readBytes = new byte[fis.available()];
while(fis.read(readBytes) != -1){//從fis讀取位元組並存入陣列readBytes,讀到位元組最後時會返回-1,迴圈就結束了
}

上面的兩部分程式碼在實際使用過程中會遇到錯誤提示,因為檔案操作可能會遇到各種問題而最終導致操作失敗,因此程式碼應該使用try / catch捕獲可能產生的異常
2. 在Android File Explorer中想要檢視寫入的檔案,卻發現白屏
關於此問題請前往站內部落格:解決Android studio中的Android 7.0 在 Android Device Monitor(DDMS)的 File Explorer不顯示目錄樹的問題
https://blog.csdn.net/itxiaolong3/article/details/70156276
3. 在Android File Explorer中想要檢視寫入的檔案,發現/data打不開
在這裡插入圖片描述
當我們去點選/data/目錄時,發現什麼都沒有,這是怎麼回事呢?原因是我們許可權不夠,當前的使用者沒有許可權訪問data目錄。
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
經大佬指點,改正後仍未解決,決定日後解決了再來更新。
據老師步驟,接下來應該是
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
4. 外部儲存需要在安卓機的設定中賦予storage許可權
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
如果在這個列表中沒有出現你的程式,建議重啟,再編譯,應該就不會有問題啦!
5. 千萬不要這樣寫路徑,例如:"/mnt/sdcard/""/sdcard/storage/"
一想到Android中到SdCard就要想到 Environment,寫入到路徑一定要用Environment,讀取到路徑一定要要用Environment,因為每部手機到SdCard到路徑都會不同Environment.getExternalStorageDirectory()

結語

經過餘老師課上的悉心指導和課後佈置的作業,我意外的有很多收穫,在本學期課程完成之後我還會將所有課後作業和期末大作業上傳至本平臺,並更新部落格,希望能夠幫到廣大網友和學弟學妹( X D )

相關文章