Android Data Storage

安卓提供了一些让我们永久保存APP数据的方式,提供了一些方法来解决数据保存的问题,例如你保存的数据是否能被其他应用程序使用,并且设置你的数据需要的空间。另外安卓还提供了content provider将一个应用程序的私有数据暴露给其他应用程序。

一.Shared Preferences

这是一个通过键值对来保存数据的存储方式。我们可用使用SharedPreferences来保存任何原始数据,例如booleans, floats, ints, longs, 和 strings。这些数据即使APP被移除仍然存在。
得到SharedPreferences需要两个方法中的一个即可:getSharedPreferences(String name, int mode)和getPreferences()。getSharedPreferences(String name, int mode)得到多个Preferences文件,而getPreferences()只得到一个Preferences文件。 
写入数据的步骤:1.调用edit()得到一个SharedPreferences.Editor对象;
             2.添加数据通过方法: putBoolean(), putString()等;
             3.调用commit()来保存。
读出数据:调用SharedPreferences的 getBoolean() , getString()等方法。
public class MainActivity extends Activity
{
    SharedPreferences preference;
    SharedPreferences.Editor editor;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        preference = getSharedPreferences("crazyit", MODE_WORLD_READABLE);
        editor = preference.edit();
        Button read = (Button) findViewById(R.id.button1);
        Button write = (Button) findViewById(R.id.button2);
        read.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                String time = preference.getString("time", null);
                int randNum = preference.getInt("random", 0);
                String result = time == null ? "您暂时还未写入数据" : "写入时间为:"+time+"\n上次生成的随机数为"+randNum;
                Toast.makeText(MainActivity.this, result, 1).show();
            }
        });

        write.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"+"hh:mm:ss");
                editor.putString("time", sdf.format(new Date()));
                editor.putInt("random", (int) (Math.random() * 100));
                editor.commit();
            }
        });
    }
}

二.内部存储Internal Storage

我们可以直接存储文件到设备的内部存储空间。保存在内部存储的文件默认是对相应的应用程序私有的,其他应用程序不能访问。当应用程序被卸载的时候,这些文件会被删除。
创建并写入一个文件的步骤:
1.调用openFileOutput()创建文件的名字和操作模式,这个方法会返回一个FileOutputStream。模式有:
MODE_PRIVATE,MODE_APPEND, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE.
2.写入内存调用write();
3.关闭流调用close().
public boolean saveContentToFile(String fileName, int mode, byte[] data)
{
    boolean flag = false;
    FileOutputStream outputStream = null;
    try
    {       
        outputStream = context.openFileOutput(fileName, mode);
        outputStream.write(data, 0, data.length); 
        flag = true;
    } catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }catch (IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        if (outputStream!=null)
        {
            try
            {
                outputStream.close();
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    return flag;
}
从内部存储中读取文件:1.调用openFileInput(),返回一个FileInputStream.
                                 2.通过方法read()读取;
                                 3.关闭流close();
public String readContentFromFile(String fileName)
{
    String result = "";
    FileInputStream inputStream = null;
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try
    {
        inputStream = context.openFileInput(fileName);
        int len = 0;
        byte[] data = new byte[1024];
        while ((len = inputStream.read(data))!=-1)
        {
            outputStream.write(data, 0, len);
        }
        return new String(outputStream.toByteArray());
    } catch (FileNotFoundException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
    return result;
}
API还提供了另外一种方法,将文件保存在工程的res/raw/目录下,通过方法openRawResource()传递R.raw.<filename>来读取。

Tip: If you want to save a static file in your application at compile time, save the file in your project res/raw/ directory. You can open it with openRawResource(), passing the R.raw. resource ID. This method returns an InputStream that you can use to read the file (but you cannot write to the original file).

另外,保存缓存文件,缓存文件不会永久保存,我们应该通过getCacheDir()来打开一个File,保存缓存的内存目录。
当设备内存很小的时候,安卓会删除缓存,但是我们不应该让系统来处理,应该让缓存消耗在一个合理的范围,例如1MB,当用户卸载应用程序的时候,这些文件会被删除。

一些有用的方法:
getFilesDir()
得到内部存储的全路径

getDir()
新建或者打开一个存在的内部存储空间

deleteFile()
在内部存储中删除一个文件。

fileList()
返回一个该应用程序保存文件的列表。

public boolean saveCacheFile(String fileName, byte[] data)
{
    boolean flag = false;
    File file = context.getFilesDir();
    FileOutputStream outputStream = null;
    try
    {
        File folder = new File(file.getAbsolutePath()+"/txt");
        if (!folder.exists())
        {
            folder.mkdir();
        }
        outputStream = new FileOutputStream(folder.getAbsolutePath()+"/"+fileName);
        outputStream.write(data, 0, data.length);
    } catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally
    {
        if (outputStream != null)
        {
            try
            {
                outputStream.close();
            } catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    System.out.println("---->>"+file.getAbsolutePath());
    return flag;
}

三.外部存储External Storage

每个安卓设备都支持一个共享的外部存储区,例如SD卡。
在使用外部存储之前,你应该调用getExternalStorageState()来检查外部媒介是否可用。
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {
    // We can read and write the media
    mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    // We can only read the media
    mExternalStorageAvailable = true;
    mExternalStorageWriteable = false;
} else {
    // Something else is wrong. It may be one of many other states, but all we need
    //  to know is we can neither read nor write
    mExternalStorageAvailable = mExternalStorageWriteable = false;
}
如果API在8及以上,我们可用通过getExternalFilesDir()来打开一个文件来作为外部存储。这个方法需要一个类型参数来确定你想保存的子目录,例如DIRECTORY_MUSIC and DIRECTORY_RINGTONES,如果为null就会得到文件的根目录。这个方法在必要时将创建一个合适的目录。通过确定目录类型可以对文件分类。API7或者以下用 getExternalStorageDirectory()。如果应用程序卸载,文件会被删除。
如果你不希望应用程序被卸载时删除文件,你可以将文件保存在一个公用的外部存储空间,这些目录在外部存储的根目录下,例如Music/, Pictures/, Ringtones/。

保存缓存文件,API8以上的使用 getExternalCacheDir()来保存,我们应该来管理缓存,而不是等系统自动删除,在应用程序卸载时,会自动删除缓存。API7以下的使用 getExternalStorageDirectory() 
public boolean saveFileToSdcard(String fileName, byte[] data)
{
    boolean flag = false;
    //先判断SD卡的状态
    String state = Environment.getExternalStorageState();
    //表示SD卡挂载在手机上,并且读写
    File root = Environment.getExternalStorageDirectory();
    System.out.println("---->>" + root);//storage/sdcard
    FileOutputStream outputStream = null;
    if (state.equals(Environment.MEDIA_MOUNTED))
    {
//          File file = new File(root, fileName);
        File file = new File(root.getAbsolutePath()+"/txt");
        if (!file.exists())
        {
            file.mkdir();
        }

        try
        {
            outputStream = new FileOutputStream(new File(file, fileName));
            outputStream.write(data, 0, data.length);
            flag = true;
        } catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }catch (IOException e)
        {
            e.printStackTrace();
        }finally
        {
            if (outputStream != null)
            {
                try
                {
                    outputStream.close();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    return flag;
}
public String readContextFromSdcard(String fileName)
{
    FileInputStream inputStream = null;
    File root = Environment.getExternalStorageDirectory();
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
    {
        File file = new File(root.getAbsolutePath()+"/txt/");
        File file2 = new File(file, fileName);
        int len = 0;
        byte[] data = new byte[1024];

        if (file2.exists())
        {
            try
            {
                inputStream = new FileInputStream(file2);
                while ((len = inputStream.read(data))!=-1)
                {
                    outputStream.write(data, 0, len);
                }
                return new String(outputStream.toByteArray());
            } catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }catch (Exception e) {
                e.printStackTrace();
            }finally{
                if (inputStream != null)
                {
                    try
                    {
                        inputStream.close();
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    return null;
}

四.数据库存储

安卓对SQLite数据库提供了完全的支持,你创建的任何数据库可以被任何应用中的类访问,但是不能被应用外的访问。
推荐的方法来创建一个新的SQLite数据库是创建一个SQLiteOpenHelper的子类并且重写onCreate()方法,在此方法里面你可以执行SQLite命令去在数据库里创建一个表。例如:
public class DictionaryOpenHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 2;
    private static final String DICTIONARY_TABLE_NAME = "dictionary";
    private static final String DICTIONARY_TABLE_CREATE =
                "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
                KEY_WORD + " TEXT, " +
                KEY_DEFINITION + " TEXT);";

    DictionaryOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DICTIONARY_TABLE_CREATE);
    }
}
你可以得到一个使用你定义的onCreate的SQLiteOpenHelper实例,然后调用getWritableDatabase()和getReadableDatabase()来读写数据库。调用后将返回一个SQLiteDatabase实例。
我们可以使用 SQLiteDatabase query()方法来查询,这个方法包含很多查询参数,例如table to query, the projection, selection, columns, grouping。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值