所有的应用程序都必然涉及数据的输入输出,Android中我们用以下几种方法来进行数据存储。
使用SharedPreferences存储数据;
当应用程序有少量的数据要保存,并且这些数据的格式简单。我们就会用到sharedpreferences来保存,比如程序的各种配置信息等。其中保存的形式为 “key-value”的键值对。
获取SharedPreferences
SharedPreferences本身是一个接口,只能通过Context 提供的 getSharedPreferences(String name,int mode) 方法来获取SharedPreferences实例。
mode 有以下几种常用的:
1. Context.MODE_PRIVATE : 数据只能被本应用读、写
2. Context.MODE_WORLD_READABLE: 数据可以被其他应用读,但不能写
3. Context.MODE_WORLD_WRITEABLE 数据可以被其他应用读、写等。
SharedPreferences位置与格式
SharedPreferences数据保存在 data/data/包名/shared_prefs 目录下, 以XML形式保存。
读取数据
SharedPreferences 接口主要负责读取应用程序的Preferences数据。他提供了以下几个常用方法来访问SharedPreferences中的key-value。
1. boolean contains(String key) :判断SharedPreferences中是否包含特定的key的值
2. abstract Map< String ,?> getAll(): 获取SharedPreferences中的全部的key-value
3. boolean getXXX(String key,xxx defaultValue) :获取指定key对应的value ,如果不存在 则返回 defaultValue,其中的XXX 为int ,string,boolean,float ,double,long 等基本类型。
写入数据
我们可以通过SharedPreferences调用edit()方法 获取 Editor对象,Editor对象提供了以下几个方法来写入数据
- SharedPreferences.Editor clear() : 清空SharedPreferences中的所有数据
- SharedPreferences.Editor putXXX(String key,XXX value) 存入指定的key 对应的数据。
- boolean commit() 当Editor 编辑完成后,调用此方法提交修改。现在建议用 apply()方法提交
实例
布局文件:
<?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:weightSum="1">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="50dp"
android:hint="name" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />
<Button
android:id="@+id/btn_clean"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="清空" />
</LinearLayout>
操作代码为:
public class AddActivity extends AppCompatActivity {
private TextView mShow;
private Button mSubmit;
private Button mClean;
SharedPreferences sp;
//几个key
private final String USER_NAME = "user_name";
private final String USER_AGE = "user_age";
private final String USER_SEX = "user_sex";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
initViews();
}
private void initViews() {
mSubmit = (Button) findViewById(R.id.btn_submit);
mShow = (TextView) findViewById(R.id.tv_name);
mClean = (Button) findViewById(R.id.btn_clean);
/**如果要在其他程序中访问本程序的sp,则要修改此处的Mode*/
sp = getSharedPreferences("table_name", Context.MODE_PRIVATE);
/**当sp中的值改变之后时回调此方法*/
sp.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Toast.makeText(AddActivity.this, "改变的key为:" + key, Toast.LENGTH_SHORT).show();
}
});
/**如果没有key对应的值,则插入新值,会回调监听方法*/
if (!sp.contains(USER_NAME)) {//如果没有user_name 则插入user_name
sp.edit().putString(USER_NAME, "遗憾").apply();
}
if (!sp.contains(USER_SEX)) {//如果没有user_name 则插入user_name
sp.edit().putString(USER_SEX, "男").apply();
}
if (!sp.contains(USER_AGE)) {//如果没有user_name 则插入user_name
sp.edit().putInt(USER_AGE, 25).apply();
}
mSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mShow.setText(sp.getAll().toString());
}
});
mClean.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sp.edit().clear().apply();
Toast.makeText(AddActivity.this, "清空了", Toast.LENGTH_SHORT).show();
}
});
}
}
我们将上面getSharedPreferences中的mode 改为Context.MODE_WORLD_READABLE
然后我们新建一个程序,来读取上述程序中的SharedPreferences。
我们在我们新建的程序中添加以下代码:
Context userTable = null;
try {
userTable = createPackageContext("要访问的sp所在的包名", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences sp = userTable.getSharedPreferences("sp的文件名", Context.MODE_WORLD_READABLE);
TextView mTextView = (TextView) findViewById(R.id.tv);
mTextView.setText(sp.getAll().toString());
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
文件存储数据;
打开应用程序的数据文件夹下的文件
Android中支持通过FileInputStream 、FileOutputStream 来访问文件内容。
Context提供了两个方法来打开文件的IO流:
FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的name文件对应输入流
FileOutputStream openFileOutput(String name,int mode) : 打开应用程序的数据文件夹下的name文件对应的输出流
int mode 的几种类型:
1. MODE_PRIVATE 该文件只能被当前程序读写
2. MODE_APPEND 以追加的方式打开文件,应用程序可以向该文件中追加内容。
3. MODE_WORLD_READABLE: 该文件可由其他应用程序读。
4. MODE_WORLD_WRITEABLE 该文件可由其他应用程序读、写。
Context中的几个方法:
1. getDir(String name,int mode) 在应用程序的文件夹下创建或者获取name对应的子目录
2. File getFilesDir() 获取该应用程序下的数据文件夹的绝对路径
3. String [] fileList () 返回该应用程序文件夹下的所有文件
4. deleteFile (String xx) 删除该应该程序下的指定文件
文件形式保存到 data/data/包名/files 目录下。
测试实例:
<?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:weightSum="1">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="50dp"
/>
<Button
android:id="@+id/btn_write"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="写入" />
<Button
android:id="@+id/btn_read"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="读取" />
</LinearLayout>
public class AddActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mShow;
private Button mWrite;
private Button mRead;
private String detail = "指定写入的内容";
private final String FILE_NAME = "my_data.txt";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
initViews();
}
private void initViews() {
mWrite = (Button) findViewById(R.id.btn_write);
mShow = (TextView) findViewById(R.id.tv_name);
mRead = (Button) findViewById(R.id.btn_read);
mWrite.setOnClickListener(this);
mRead.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_write:
write(detail);
break;
case R.id.btn_read:
read();
mShow.setText(read());
break;
}
}
/**
* 读取内容
*/
@Nullable
private String read() {
try {
FileInputStream fis = openFileInput(FILE_NAME);
byte[] buff = new byte[1024];
int hasRead = 0;
StringBuilder sb = new StringBuilder("");
while ((hasRead = fis.read(buff)) > 0) {
sb.append(new String(buff, 0, hasRead));
}
return sb.toString();
} catch (java.io.IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 写入内容
*/
private void write(String detail) {
try {
FileOutputStream fos = openFileOutput(FILE_NAME, MODE_APPEND);
PrintStream ps = new PrintStream(fos);
ps.println(detail);
ps.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
打开手机SD卡中的文件:
为了更好的存取应用程序的大文件数据,应用程序需要读、写SD卡中的文件。
读写SD卡文件的步骤:
1. 调用Environment 的 getExternalStorageState()方法判断是否有SD卡,并且程序具有读写sd卡的权限 。
//如果有sd卡,并且有读写权限则下面语句返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
2. Environment.getExternalStorageDirectory() 来获取sd卡的目录
3. 用 FileInputStream 、FileOutputStream、FileReader、FileWriter读、写SD卡中的文件。
4. 读写SD卡需要特定的权限才可以正常的操作。
我们往SD卡中的特定文件中写内容
/**
* 写入内容
*/
private void write(String detail) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdcardDir = Environment.getExternalStorageDirectory();//获取外置sd卡路径
try {
File f = new File(sdcardDir.getCanonicalFile() + File.separator + FILE_NAME);
//判断f是否已经创建了
if (!f.exists()) {
try {
//没有创建,则创建
f.getParentFile().mkdirs();
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//以指定文件创建RandomAccessFile
RandomAccessFile raf = new RandomAccessFile(f, "rw");
raf.seek(f.length());
raf.write(detail.getBytes());
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
读我们写入的内容
/**
* 读取内容
*/
@Nullable
private String read() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdDir = Environment.getExternalStorageDirectory();
try {
//获取指定文件对应的输入流
FileInputStream fis = new FileInputStream(sdDir.getCanonicalFile() + File.separator + FILE_NAME);
//将输入流包装成BufferReader
BufferedReader btr = new BufferedReader(new InputStreamReader(fis));
StringBuilder sb = new StringBuilder("");
String line = null;
while ((line = btr.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
需要的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
读取SD卡中的所有文件:
private void searchAndShow() {
File file = new File("/mnt/sdcard/");
if (file.exists()) {
fileList = file.listFiles();
}
if (fileList != null) {
adapter = new MyAdapter(this, fileList);
mListView.setAdapter(adapter);
}
/**
* 点击事件
* */
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (fileList[position].isFile()) {
return;
}
File[] temp = fileList[position].listFiles();
if (temp.length == 0 || temp == null) {
Toast.makeText(AddActivity.this, "此文件为空", Toast.LENGTH_SHORT).show();
//跳转一个空的Activity
startActivity(new Intent(AddActivity.this,EmptyActivity.class));
}else {
currentParent = fileList[position];
adapter = new MyAdapter(AddActivity.this,temp);
mListView.setAdapter(adapter);
}
}
});
}
添加一个返回按钮:
Button mBack = (Button) findViewById(R.id.btn_back);
mBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!currentParent.getCanonicalPath().equals("/mnt/sdcard")){
currentParent = currentParent.getParentFile();
adapter = new MyAdapter(AddActivity.this,currentParent.listFiles());
mListView.setAdapter(adapter);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
适配器:
public class MyAdapter extends BaseAdapter {
File [] fileList;
Context mContext;
public MyAdapter(Context mContent, File[] fileList) {
this.mContext = mContent;
this.fileList = fileList;
}
@Override
public int getCount() {
return fileList.length;
}
@Override
public Object getItem(int i) {
return fileList[i];
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
if (view == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
holder = new ViewHolder();
holder.tv_name = (TextView) view.findViewById(R.id.item_name);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.tv_name.setText(fileList[i].getName());
return view;
}
class ViewHolder {
TextView tv_name;
}
}
SQLite数据库存储数据;
http://blog.youkuaiyun.com/qq_27561483/article/details/52610686