آموزش برنامه نویسی اندروید با اندروید استودیو (بخش پنجاه و هشتم: خواندن از انواع فایل در دایرکتوری معین )

استاندارد

در بخش قبلی در مورد خواندن از فایل صحبت شد. دیدیم که با استفاده از دایرکتوری معین و نام فایل text ، می توانستیم محتویات و نوشته های آن را مشاهده نماییم.

در واقع محتویات فایل، به یک متغیر رشته ای String ، تبدیل می شد و با استفاده از پیغام Toast به کاربر نمایش داده می شود.

در این قسمت هم می خواهیم ، عمل خواندن از فایل را انجام دهیم ولی اینبار می خواهیم که این کار را با استفاده از کلاس FileInputStream انجام دهیم.

با استفاده از کلاس FileInputStream می توانیم عملیات بیشتری را بر روی فایل انجام دهیم.

و حتی در برخورد با انواع فایل های مختلف، راحتتر عمل نماییم. زیرا این کلاس، فایل را به صورت بایت در می آورد.

برای این کار باید کد زیر را در قسمت MainActivity.java مورد استفاده قرار دهید.

int length = (int) file.length(); // به دست آوردن طول فایل

byte[] bytes = new byte[length]; //  تعریف متغیر آرایه ای از نوع بایت

FileInputStream in = new FileInputStream(myfile); // نام فایل است myfile
try {
    in.read(bytes); //  bytes خواندن جریان بایت های فایل و نوشتن آن بر روی متغیر
} finally {
    in.close();
}

String contents = new String(bytes); //   به متغیر رشته ای جهت نمایش byte  تبدیل متغیر

البته فرض بر آنست که فایل به صورتی که در بخش های قبلی توضیح داده شده، تعریف شده است.

مثلا به صورت زیر:

String fileName = "1.txt";
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String pathDir = baseDir + "/Android/";

File myfile = new File(pathDir + File.separator + fileName);

شرح کد:

فرض می کنیم فایلی به صورتی که در تصویر مشاهده می کنید وجود دارد.

و محتویات آن به این شکل است:

پس مشخصات این فایل بدین صورت است:

      Name: 1.txt

/Directory: /Android

Content: Gsm Developers

دقیقا مثل بخش قبلی ، نام و دایرکتوری فایل را به صورت زیر در کدجاوای پروژه مشخص می کنیم:

String fileName = "1.txt";
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String pathDir = baseDir + "/Android/";

در مرحله ی بعدی یک شی به نام myfile از کلاس File می سازیم و با استفاده از مسیر دایرکتوری که به برنامه گفتیم و نام فایلی که می خواهیم آن را تعریف می کنیم.

File myfile = new File(pathDir + File.separator + fileName);

در قسمت اول، pathDir یعنی مسیر دایرکتوری و در قسمت سوم، fileName یعنی همان نام فایل از ورودی های سازنده برای این شی می باشند.

این موارد، در بخش قبلی نیز توضیح داده شد. ولی در این قسمت می خواهیم از کلاس FileInputStream که در واقع جریان ورودی فایل را می خواند استفاده نماییم.

بدین منظور در ابتدا طول فایل را به دست می آوریم:

int length = (int) myfile.length();

سپس یک متغیر آرایه ای به نام bytes از نوع byte معرفی می کنیم و تعداد خانه های آن را برابر با طول فایل در نظر می گیریم.

byte[] bytes = new byte[length];

در مرحله ی بعدی با استفاده از کلاس FileInputStream ، جریان ورودی فایل را به بایت تبدیل کرده و در متغیر آرایه ای bytes می ریزیم.

FileInputStream in = new FileInputStream(myfile);
try {
    in.read(bytes);
} finally {
    in.close();
}

وقتی فایل شما به صورت bytes در بیاید می توانید از آن در قسمت های مختلف کد خود، استفاده نمایید. ولی به دلیل سادگی و پیوسته بودن مطالب در اینجا ما مانند بخش قبل، آن را تبدیل به رشته string می کنیم.

پس در قسمت بعدی، متغیر آرایه ای bytes را به رشته String تبدیل می کنیم تا بتوانیم با استفاده از پیغام Toast آن را به کاربر نمایش دهیم.

String contents = new String(bytes);

در آخر با استفاده از پیغام Toast ، محتویات این رشته به کاربر نمایش داده می شود.

Toast.makeText(getApplicationContext(),contents, Toast.LENGTH_SHORT).show();

نکته:

در بعضی کامپایلرها مثلا Android Studio ، به دلیل آن که فایل ممکن است در حافظه موجود نباشد یا به هر دلیلی قابل خواندن نباشد، دو کد قبلی را در ساختار try-catch می نویسیم.

FileInputStream in = null;
        try {
            in = new FileInputStream(myfile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            in.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

برای دادن دسترسی ها باید به قسمت AndroidManifest.xml رفته و کد زیر را برای خواندن از حافظه ی خارجی بنویسیم.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

پروژه را Run می کنیم.

کد کامل MainActivity.java

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String fileName = "1.txt";
        String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        String pathDir = baseDir + "/Android/";

        File myfile = new File(pathDir + File.separator + fileName);

        int length = (int) myfile.length();
        byte[] bytes = new byte[length];

        FileInputStream in = null;
        try {
            in = new FileInputStream(myfile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            in.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        String contents = new String(bytes);
        Toast.makeText(getApplicationContext(),contents, Toast.LENGTH_SHORT).show();

    }
}

آموزش برنامه نویسی اندروید با اندروید استودیو (بخش پنجاه و پنجم: بررسی امکان دسترسی خواندن و نوشتن در حافظه )

استاندارد

دسترسی خواندن و نوشتن در حافظه موضوع مورد بحث این بخش است.

در این بخش از آموزش برنامه نویسی اندروید، می خواهیم بررسی کنیم که آیا می توانیم فایلی را در حافظه ی خارجی توسط اپلیکیشن بنویسیم؟

به عبارتی آیا اپلیکیشن ما اجازه ی این کار را دارد؟

این بخش، پیش نیاز کار با فایل ها در برنامه نویسی اندروید است.

پس بررسی موضوع دسترسی خواندن و نوشتن در حافظه ی خارجی ، می تواند به ما در کار با فایل ها کمک نماید.

قبل از هر چیز دقت نمایید که حافظه ی گوشی و یا تبلت اندرویدی به دو قسمت حافظه ی داخلی و حافظه ی خارجی تقسیم می شود.

که نام انگلیسی آن ها به ترتیب Internal Memory و External Memory می باشد.

کاربر به Internal Memory دسترسی ندارد. بلکه به External Memory دسترسی دارد.

هدف ما در این بخش نیز بررسی دسترسی اپلیکیشن به این حافظه می باشد.

دقت کنید که External Memory را با Sd Card که یعنی کارت حافظه ی Sd ، با قابلیت جداشدن است، اشتباه نگیرید.

برنامه نویسی جاوای این پروژه

به قسمت کد جاوای برنامه یعنی MainActivity.java می رویم.

در ابتدا در متد ()onCreate دو متیر از نوع Boolean معرفی می کنیم.

boolean memoryExternalStorageAvailable = false;
boolean memoryExternalStorageWrite = false;

متغیر اولی، یعنی memoryExternalStorageAvailable بررسی می کند که آیا می توان به حافظه دسترسی پیدا کرد؟ به عبارتی آیا حافظه ی خارجی برای اپلیکیشن حاضر (Available) است؟ (Read)

متغیر دومی، یعنی memoryExternalStorageWrite بررسی می کند که آیا امکان نوشتن در حافظه وجود دارد؟ (Write)

کاری که می خواهیم انجام دهیم اینست که با بررسی با استفاده از کدهایی در قسمت بعدی، در صورت مثبت بودن جواب این سوالات، مقدار True و در صورت منفی بودن جواب این سوالات، مقدار false را به متغیر مربوطه بدهیم.

با استفاده از کلاس Environment می توان به حافظه ی خارجی دسترسی داشت.

پس یک متغیر رشته ای از یکی از متدهای این کلاس می سازم. و نامش را state به معنی وضعیت می گذارم.

String state = Environment.getExternalStorageState();

مشاهده می کنید که این متغیر یک نوع رشته از متد getExternalStorageState می باشد. که در واقع متد getExternalStorageState وضعیت حافظه ی خارجی را به ما اطلاع می دهد.

در قسمت بعدی با استفاده از یک ساختار کنترلی if-else به بررسی این موضوع می پردازم که آیا حافظه ی خارجی بر روی دستگاه، سوار (mount) شده است یا خیر؟

if (Environment.MEDIA_MOUNTED.equals(state)) {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            memoryExternalStorageAvailable = true;
            memoryExternalStorageWrite = false;
        } else {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = false;
        }

در همین ساختار کنترلی است که مقدارهای دو متغیر Boolean ی که در ابتدا تعریف نمودیم، مشخص می شود.

در if دوم، با استفاده از MEDIA_MOUNTED_READ_ONLY به معنی آنست که اگر ، حافظه ی خارجی به صورت Read Only است، فقط متغیر memoryExternalStorageAvailable مقدار True را داشته باشد. که به معنی فقط خواندنی است.

برای این که این موضوع را به اطلاع کاربر برسانیم بهتر است از یک پیغام Toast استفاده کنیم.

پس دو رشته به نام های Readable و Writeable می سازم.

مقدار اولیه ی این دو رشته به ترتیب برابر Not Readable و Not Writable است. ولی اگر از دستور if با موفقیت عبور نمایند، مقدار Can Read Data From External Memory و Can Write Data into External Memory به آن ها داده می شود که این پیغام در آخر با استفاده از یک Toast به کاربر نمایش داده می شود.

String Readable = "Not Readable";
if(memoryExternalStorageAvailable)
    Readable="Can Read Data From External Memory";
String Writeable = "\nNot Writeable";
if(memoryExternalStorageWrite)
     Writeable="\nCan Write Data into External Memory";
Toast.makeText(getApplicationContext(), Readable+Writeable, Toast.LENGTH_SHORT).show();

کد کامل MainActivity.java

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        boolean memoryExternalStorageAvailable = false;
        boolean memoryExternalStorageWrite = false;
        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state)) {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = true;
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            memoryExternalStorageAvailable = true;
            memoryExternalStorageWrite = false;
        } else {
            memoryExternalStorageAvailable = memoryExternalStorageWrite = false;
        }
        String Readable = "Not Readable";
        if(memoryExternalStorageAvailable)
            Readable="Can Read Data From External Memory";
        String Writeable = "\nNot Writeable";
        if(memoryExternalStorageWrite)
            Writeable="\nCan Write Data into External Memory";
        Toast.makeText(getApplicationContext(), Readable+Writeable, Toast.LENGTH_SHORT).show();

    }
}

در برخی منابع، ذکر شده که برای دادن دسترسی ها به اپلیکیشن در صورت نیاز باید کدهای زیر برای دسترسی به حافظه ی خارجی در AndroidManifest.xml نوشته شوند.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

پروژه را Run می کنیم.