您的位置:首页 > 移动开发 > Android开发

Android数据存储(一)

2016-05-25 20:55 363 查看
一)文件存储方式

通过java里的文件读取流和写入流来对安卓的文件进行读写操作

安卓应用程序资源分类可以分为两大类,assets和res.其中res保存的文件大都会被编译,并且会被赋予资源id,这样我们可以在程序中通过id来访问res类的资源,res按不同用途可以分为anim,animator,color,drawable,layout,raw,menu,values,xml这九种。

1)读取assets中的文件数据:assets类资源放在工程目录的assets子目录下,它里面保存的是一些原始文件,可以以任何方式来进行组织,这些文件最终会原装不动的打包在apk文件里。

访问assets文件资源通过getAssets().open()来打开文件名,注意inputStreamReader()里面设置编码格式为utf-8,这样统一编码格式,防止乱码出现。

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.get_assets:
try {
InputStream in=getResources().getAssets().open("info.txt");
InputStreamReader isr=new InputStreamReader(in,"utf-8");
BufferedReader bfr=new BufferedReader(isr);
System.out.println(bfr.readLine());
String s="";
while ((s=bfr.readLine())!=null){//读取文件内容
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
break;


2)读取raw文件:raw文件和assets文件一样都是原封不动的打包在apk文件,不过raw会被赋予资源id,,这样我们就可以在程序里通过id来访问他们。

通过openRawResource()传入文件的id来访问,传入R.raw.filename

case R.id.get_raw:

//                try {
//                    InputStream in = getResources().openRawResource(R.raw.inforaw);
//                    InputStreamReader isr = new InputStreamReader(in, "utf-8");
//                    BufferedReader brf = new BufferedReader(isr);
//                    String str = "";
//                    while ((str=brf.readLine())!=null){
//                        System.out.println(str);
//                    }
//                } catch (UnsupportedEncodingException e) {
//                    e.printStackTrace();
//                }catch (IOException e){
//                    e.printStackTrace();
//                }
//                break;

3)读写内部存储的文件数据

存储在内部还是外部

所有的Android设备均有两个文件存储区域:"internal" 与 "external" 。 这两个名称来自于早先的Android系统,当时大多设备都内置了不可变的内存(internal storage)及一个类似于SD card(external storage)这样的可卸载的存储部件。之后有一些设备将"internal" 与 "external" 都做成了不可卸载的内置存储,虽然如此,但是这一整块还是从逻辑上有被划分为"internal"与"external"的。只是现在不再以是否可卸载进行区分了。
下面列出了两者的区别:

Internal storage:

总是可用的
这里的文件默认只能被我们的app所访问。
当用户卸载app的时候,系统会把internal内该app相关的文件都清除干净。
Internal是我们在想确保不被用户与其他app所访问的最佳存储区域。

External storage:

并不总是可用的,因为用户有时会通过USB存储模式挂载外部存储器,当取下挂载的这部分后,就无法对其进行访问了。
是大家都可以访问的,因此保存在这里的文件可能被其他程序访问。
当用户卸载我们的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。
External是在不需要严格的访问权限并且希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。

我们可以读写data目录下的内部存储数据,比如我们把在EditText里面写的文字写入我们定义的一个filename,然后在data目录下可以找到filename的文件里存放着我们EditText的内容,并且可以读取出来。

模式指定为MODE_PRIVATE别的程序就不能访问这个文件。

系统默认程序的安装位置是内部,我们也可以在Manifest里面修改。当程序卸载后,其内部文件也会被删除。

我们的app的internal storage 目录以app的包名作为标识存放在Android文件系统的特定目录下[data/data/com.example.xx]。 从技术上讲,如果文件被设置为可读的,那么其他app就可以读取该internal文件。然而,其他app需要知道包名与文件名。若没有设置为可读或者可写,其他app是没有办法读写的。因此我们只要使用了MODE_PRIVATE ,那么这些文件就不可能被其他app所访问。

case R.id.get_write:
try {
FileOutputStream fileOutputStream=openFileOutput(filename, Context.MODE_PRIVATE);
OutputStreamWriter  outputStreamWriter=new OutputStreamWriter(fileOutputStream,"utf-8");
outputStreamWriter.write(write.getText().toString());
outputStreamWriter.flush();
fileOutputStream.flush();
outputStreamWriter.close();
fileOutputStream.close();
Toast.makeText(MainActivity.this,"写入完成",Toast.LENGTH_SHORT).show();

} catch (FileNotFoundException e) {

}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}

break;

case R.id.read:

try {

FileInputStream fileInputStream=openFileInput(filename);
InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream,"utf-8");
char[] input=new char[fileInputStream.available()];//文件长度设置为字符数组长度
inputStreamReader.read(input);
inputStreamReader.close();
fileInputStream.close();
String str=new String(input); //字符数组转换为字符串
show.setText(str);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}

break;

4)读取外部存储的文件数据

写数据到外部存储,需要声明权限(在android4.4之后外部存储的读写都不再需要声明权限)

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


如果声明了写权限,那么程序默认有读取的权限。

否则如果程序只需要读取的权限,我们应该声明读取权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
因为存储在外部的数据有可能发生变化,比如sd卡拔掉,所以在读写之前我们应该先对其可用性状态进行检查,使用getExternalStorageState()进行检查,如果返回值是MEDIA_MOUNTED,那么可以进行读写

public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
如果我们只需要对程序的是否可读的状态进行检测,那么:

/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}


存储在外部的数据分为public 和private两种,public files在程序卸载时应该保留,比如被程序拍摄的照片或者下载的文件。private files在程序卸载的时候应该删除,因为这些缓存文件对其他程序来说并没有任何意义。

以public 形式向外部存储写入数据:getExternalStoragePublicDirectory()来构建一个File对象表示存储在External Storage目录,其包含一个指定文件类型的参数,以便于与其他public 文件区别,比如DIRECTORY_MUSIC和DIRECTORY_PICTURES

public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}


以private形式存储,getExternalFileDir来获取File对象,表示存储在app下的参数文件夹下,比如下面例子的(albumName)。这个文件夹会在程序卸载的时候删除。

public File getAlbumStorageDir(Context context, String albumName) {
// Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}


这样将文件保存在外部存储之后,就可以进行读取的操作。

二)SharedPreference的使用

SharedPreference是一种轻型的数据存储形式,使用键值对来读写,并且通过SharedPrefrence.Editor来存储。

其存储位置在/data/data/com.xxxxxxx(package name)/shared-prefs目录。

我们可以通过getSharedPreFerences()和getPreFerences()来创建Shared Preferences文件,前者需要在参数里设置一个文件名,并且通过Context来执行;后者不需要设置文件名,而且是通过Activity来执行

private SharedPreferences   preference=getPreferences(Activity.MODE_PRIVATE);
private Editor  editor=preference.edit();


sharedPreferences()的读和写操作:

@Override
public void onClick(View v) {

switch (v.getId()) {
case R.id.write:
editor.putString(KEY, input.getText().toString());
if (editor.commit()) {
Toast.makeText(MainActivity.this, "写入数据成功",Toast.LENGTH_SHORT).show();
}

break;
case R.id.read:
String data=preference.getString(KEY, "数据不存在");
Toast.makeText(MainActivity.this,data, Toast.LENGTH_SHORT).show();

break;
default:
break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: