Android存储与加载JSON格式的本地文件
Android存储与加载JSON格式的本地文件
请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)
Android存储与加载JSON格式的本地文件,直接读写在SD卡上。其它的有用到Spinner、Adapter、TableLayout、TableRow等。
1、创建Spinner的布局文件(activity_configure.xml)
a) 使用LinearLayout线性布局,加载Spinner和TableLayout布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义一个城市信息下拉菜单-->
<Spinner
android:id = "@+id/Spinner_city"
android:layout_width = "wrap_content"
android:layout_height ="wrap_content"
android:layout_gravity= "center" >
</Spinner >
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity= "center" >"
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SensorText: " />
<EditText
android:id="@+id/EditText_Sensor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="EditText"/>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UnitText: " />
<EditText
android:id="@+id/EditText_Unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="EditText"/>
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ChType: " />
<EditText
android:id="@+id/EditText_Type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="EditText"/>
</TableRow>
<TableRow
android:id="@+id/tableRow4"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="K: " />
<EditText
android:id="@+id/EditText_K"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="EditText"/>
</TableRow>
<TableRow
android:id="@+id/tableRow5"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B: " />
<EditText
android:id="@+id/EditText_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="EditText"/>
</TableRow>
<TableRow
android:id="@+id/tableRow6"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="isChecked: " />
<CheckBox
android:id="@+id/CheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</TableRow>
<TableRow
android:id="@+id/tableRow7"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="@+id/Button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定" />
<Button
android:id="@+id/Button_return"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回" />
</TableRow>
</TableLayout>
</LinearLayout>
2、创建单个配置文件SysCh类(SysCh.java)
a) 自定义JSON需要常量字符串,以及声明SysCh所需的6个变量
i. StringSensor;//文本
ii. StringUnit;// 单位
iii. int Type;// 类型
iv. double K;// 斜率
v. double B;//截距
vi. booleanisChecked; //是否被选中
b) 重写SysCh()的默认构造函数
c) 添加一个接受JSONObject对象的构造方法。将传入的JSONObject转换成配置文件所需的变量。
d) 最后实现toJSON()方法,返回JSON格式的SysCh对象。
package com.example.engineering5.ChLab;
import org.json.JSONException;
import org.json.JSONObject;
/******************
*
* 系统通道配置信息
*
* @author Administrator
*
*/
public class SysCh {
private static final String JSON_Sensor="sensor";
private static final String JSON_Unit="unit";
private static final String JSON_Type="type";
private static final String JSON_K="k";
private static final String JSON_B="b";
private static final String JSON_isChecked="isChecked";
public String Sensor; // 传感器,通道1-64 对应的传感器文本
public String Unit; // 单位,通道1-64 对应的单位
public int Type; // 类型,范围0~3,0:关闭,1:温度,2:压力,3:流量,4:转速,
public double K; // 斜率 y=Kx+b
public double B; // 截距
public boolean isChecked; //是否被选中显示
public SysCh(){
}
/******************
*
* 接收JSON的构造方法
* @param json
* @throws JSONException
*/
public SysCh(JSONObject json) throws JSONException{
Sensor = json.getString(JSON_Sensor);
Unit = json.getString(JSON_Unit);
Type = json.getInt(JSON_Type);
K = json.getDouble(JSON_K);
B = json.getDouble(JSON_B);
isChecked = json.getBoolean(JSON_isChecked);
}
/******************
*
* @return 以JSON格式保存SysCh对象
* @throws JSONException
*/
public JSONObject toJSON() throws JSONException{
JSONObject json = new JSONObject();
json.put(JSON_Sensor, Sensor);
json.put(JSON_Unit, Unit);
json.put(JSON_Type, Type);
json.put(JSON_K, K);
json.put(JSON_B, B);
json.put(JSON_isChecked, isChecked);
return json;
}
}
3、创建存储和加载JSON数据的JSONSerializer类(JSONSerializer.java)
a) 重写JSONSerializer的构造函数,传入存储和加载本地文件所需的文件名和所需的当前的Activity
b) 创建加载JSON格式的本地文件的函数,返回SysCh的集合。
i. 使用Context的openFileInput(…)方法,传入文件名,打开应用沙盒文件目录路径下的目标文件,也可以使用new FileInputStream()方法传入文件参数,新建InputStream对象。
ii. 然后读取文件转换成JSONObject类型的string,再解析为JSONArray,最后再解析为ArrayList。
iii. 注意:在finally代码块中,调用reader.close()方法。这样,即使发生错误,也可以保证完成底层文件句柄的释放。
c) 创建存储JSON格式的本地文件的函数。传入SysCh集合。
i. 使用Context.openFileOutput(...)方法,传入文件名以及文件操作模式参数,系统会自动将传入的文件名附加到应用沙盒文件目录路径/data/data/<package name>/files之后。
ii. 然后在该路径下创建并打开文件,等待数据写入。调用openFileOutput(...)方法获得OutputStream对象,也可以使用new FileOutputStream()方法传入文件参数,新建得OutputStream对象。再用其创建一个新的OutputStreamWriter对象,最后调用该对象的写入方法写入数据。
iii. 至于JaveString与最终写入文件的原始字节流之间的转换,则不必担心,OutputStreamWriter会搞定一切。最后在系统根目录下再写一份配置文件用来给自己看。
package com.example.engineering5.JSONSerializer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONTokener;
import com.example.engineering5.ChLab.DateCh;
import com.example.engineering5.ChLab.SysCh;
import android.content.Context;
import android.os.Environment;
/*********************
*
* JSONSerializer类负责读取SysCh数组列表的中的数据,进行数据格式转换,然后写入JSON文件
*
* @author Administrator
*
*/
public class SysChsJSONSerializer {
private Context mContext;
private String SysChs_Filename="配置文件.txt";
private File mFolder,mFile;
public SysChsJSONSerializer(Context c){
mContext = c;
//在系统根目录下新建"工程机械手持数据采集分析配置文件"文件夹
mFolder=new File(Environment.getExternalStorageDirectory(),"工程机械手持数据采集分析配置文件");
mFolder.mkdir();
//在该文件夹下新建"配置文件.txt"文件
mFile=new File(mFolder,SysChs_Filename);
}
/************************
*
* @return JSON格式的本地配置文件ArrayList<SysCh>
*
* @throws IOException
* @throws JSONException
*/
public ArrayList<SysCh> loadSysChs() throws IOException, JSONException{
ArrayList<SysCh> SysChs=new ArrayList<SysCh>();
BufferedReader reader = null;
try {
// Open and read the file into a StringBuilder
//将读取应用沙盒文件目录路径下的文件改成写到根目录下的新建文件夹中的新家文件中
//InputStream mInputStream=mContext.openFileInput(mFilename);
InputStream mInputStream = new FileInputStream(mFile);
reader = new BufferedReader(new InputStreamReader(mInputStream));
StringBuilder jsonString = new StringBuilder();
String line = null;
while((line=reader.readLine())!=null){
// line breaks are omitted and irrelevant
jsonString.append(line);
}
// Parse the JSON using JSONTokener
JSONArray array = (JSONArray) new JSONTokener(jsonString.toString()).nextValue();
// Build the array of SysChs form JSONObjects
for (int i = 0; i < array.length(); i++) {
SysChs.add(new SysCh(array.getJSONObject(i)));
}
} catch (FileNotFoundException e) {
// TODO: handle exception
} finally{
if (reader!=null) {
reader.close();
}
}
return SysChs;
}
/****************************
*
* 存储JSON格式的本地配置文件ArrayList<SysCh>
*
* @param SysChs
* @throws JSONException
* @throws IOException
*/
public void saveSysChs(ArrayList<SysCh> SysChs) throws JSONException, IOException {
// Build an array in JSON
JSONArray array = new JSONArray();
for (SysCh s : SysChs)
array.put(s.toJSON());
//Write the file to disk
Writer writer = null;
try {
//将写在应用沙盒文件目录路径下的文件改成写到根目录下的新建文件夹中的新家文件中
//OutputStream out = mContext.openFileOutput(mFilename, Context.MODE_PRIVATE);
OutputStream out = new FileOutputStream(mFile);
writer = new OutputStreamWriter(out);
writer.write(array.toString());
} catch (Exception e) {
// TODO: handle exception
} finally{
if (writer!=null) {
writer.close();
}
}
}
}
4、创建配置文件集合类SysChLab(SysChLab.java)
a) 重写SysChLab的构造函数。该函数中我们首先尝试加载SysCh的集合,如果加载失败或者加载的集合为空,则我们new一个空集合,然后初始化它。
b) 创建存储JSON格式的SysCh集合的函数。函数中尝试调用JSONSerializer的存储方法。成功则Toast告知用户,保存成功。失败则Toast告知用户,保存失败。
c) 创建初始化SysCh集合的函数。应用程序第一次安装的时候是没有SysCh的本地配置文件的,就要进行初始化。
package com.example.engineering5.ChLab;
import java.util.ArrayList;
import com.example.engineering5.JSONSerializer.SysChsJSONSerializer;
import android.content.Context;
import android.widget.Toast;
public class SysChLab {
private SysChsJSONSerializer mSerializer;
public ArrayList<SysCh> mSysChs;
private Context mAppContext;
public SysChLab(Context appContext){
mAppContext = appContext;
mSerializer= new SysChsJSONSerializer(mAppContext);
try {
//加载本地数组
mSysChs = mSerializer.loadSysChs();
//如果加载的数组为空,则初始化
if (mSysChs.isEmpty()) {
init();
}
} catch (Exception e) {
// TODO: handle exception
//如果加载数组失败,则new一个空的数组,再初始化它
mSysChs=new ArrayList<SysCh>();
init();
Toast.makeText(mAppContext, "加载JSON失败", Toast.LENGTH_SHORT).show();
}
}
public boolean saveSysChs(){
try {
mSerializer.saveSysChs(mSysChs);
Toast.makeText(mAppContext, "保存成功",Toast.LENGTH_SHORT).show();
return true;
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(mAppContext, "保存失败",Toast.LENGTH_SHORT).show();
return false;
}
}
private void init(){
SysCh []ch=new SysCh[16];
for (int i = 0; i < 16; i++) {
ch[i]=new SysCh();
}
ch[0].Sensor="泵供油流量";
ch[0].Unit="℃";
ch[0].Type=1;
ch[0].K=1;
ch[0].B=1.1;
ch[0].isChecked=true;
ch[1].Sensor="泵供油压力";
ch[1].Unit="Mpa";
ch[1].Type=1;
ch[1].K=1;
ch[1].B=1.2;
ch[1].isChecked=true;
ch[2].Sensor="泵供油流量";
ch[2].Unit="℃";
ch[2].Type=3;
ch[2].K=34;
ch[2].B=1;
ch[2].isChecked=true;
ch[3].Sensor="泵供油压力";
ch[3].Unit="Mpa";
ch[3].Type=4;
ch[3].K=1;
ch[3].B=1.56;
ch[3].isChecked=true;
ch[4].Sensor="泵供油流量";
ch[4].Unit="℃";
ch[4].Type=4;
ch[4].K=1;
ch[4].B=1;
ch[4].isChecked=true;
ch[5].Sensor="泵供油压力";
ch[5].Unit="Mpa";
ch[5].Type=3;
ch[5].K=1;
ch[5].B=1;
ch[5].isChecked=true;
ch[6].Sensor="泵供油流量";
ch[6].Unit="℃";
ch[6].Type=2;
ch[6].K=1;
ch[6].B=1;
ch[6].isChecked=true;
ch[7].Sensor="泵供油压力";
ch[7].Unit="Mpa";
ch[7].Type=1;
ch[7].K=1;
ch[7].B=1;
ch[7].isChecked=true;
ch[8].Sensor="泵供油流量";
ch[8].Unit="℃";
ch[8].Type=0;
ch[8].K=1;
ch[8].B=1;
ch[8].isChecked=true;
ch[9].Sensor="泵供油压力";
ch[9].Unit="Mpa";
ch[9].Type=0;
ch[9].K=1;
ch[9].B=1;
ch[9].isChecked=true;
ch[10].Sensor="泵供油流量";
ch[10].Unit="℃";
ch[10].Type=0;
ch[10].K=1;
ch[10].B=1;
ch[10].isChecked=true;
ch[11].Sensor="泵供油压力";
ch[11].Unit="Mpa";
ch[11].Type=0;
ch[11].K=1;
ch[11].B=1;
ch[11].isChecked=true;
ch[12].Sensor="泵供油流量";
ch[12].Unit="℃";
ch[12].Type=0;
ch[12].K=1;
ch[12].B=1;
ch[12].isChecked=true;
ch[13].Sensor="泵供油压力";
ch[13].Unit="Mpa";
ch[13].Type=0;
ch[13].K=1;
ch[13].B=1;
ch[13].isChecked=true;
ch[14].Sensor="泵供油流量";
ch[14].Unit="℃";
ch[14].Type=0;
ch[14].K=1;
ch[14].B=1;
ch[14].isChecked=true;
ch[15].Sensor="泵供油压力";
ch[15].Unit="Mpa";
ch[15].Type=0;
ch[15].K=1;
ch[15].B=1;
ch[15].isChecked=true;
for (int i = 0; i < ch.length; i++) {
mSysChs.add(ch[i]);
}
}
}
5、创建ConfigureActivity(ConfigureActivity.java)
a) 各种控件的实例化
b) 新建List的集合,即Spinner的下拉列表的选项
c) 新建Spinner的适配器,传入android.R.layout.simple_spinner_item和List集合等参数
d) 设置适配器下拉列表下拉时的菜单样式
e) 将适配器加载到Spinner上。
f) 设置Spinner的点击事件。
package com.example.engineering5.Activity;
import java.util.ArrayList;
import java.util.List;
import com.example.engineering5.R;
import com.example.engineering5.R.id;
import com.example.engineering5.R.layout;
import com.example.engineering5.ChLab.SysChLab;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
public class ConfigureActivity extends Activity{
private String IP;
private String Port;
private List<String> list = new ArrayList<String>();
private Spinner mySpinner;
private EditText mEditText_Sensor;
private EditText mEditText_Unit;
private EditText mEditText_Type;
private EditText mEditText_K;
private EditText mEditText_B;
private CheckBox mCheckBox;
private Button mButton_ok;
private Button mButton_return;
private ArrayAdapter<String> adapter;
private SysChLab mSysChLab;
private int num=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_configure);
/*************获得登录界面传递过来的IP和port**************/
Intent mIntent = getIntent();
IP=mIntent.getStringExtra("ip");
Port=mIntent.getStringExtra("port");
mSysChLab=new SysChLab(this);
//第一步:添加一个下拉列表项的list,这里添加的项就是下拉列表的菜单项
list.add("通道一");
list.add("通道二");
list.add("通道三");
list.add("通道四");
list.add("通道五");
list.add("通道六");
list.add("通道七");
list.add("通道八");
list.add("通道九");
list.add("通道十");
list.add("通道十一");
list.add("通道十二");
list.add("通道十三");
list.add("通道十四");
list.add("通道十五");
list.add("通道十六");
//控件实例化
mySpinner = (Spinner)findViewById(R.id.Spinner_city);
mEditText_Sensor=(EditText) findViewById(R.id.EditText_Sensor);
mEditText_Type=(EditText) findViewById(R.id.EditText_Type);
mEditText_Unit=(EditText) findViewById(R.id.EditText_Unit);
mEditText_K=(EditText) findViewById(R.id.EditText_K);
mEditText_B=(EditText) findViewById(R.id.EditText_B);
mCheckBox=(CheckBox) findViewById(R.id.CheckBox);
mButton_ok=(Button) findViewById(R.id.Button_ok);
mButton_return=(Button) findViewById(R.id.Button_return);
//确认按钮的监听器
mButton_ok.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
mSysChLab.mSysChs.get(num).Sensor=mEditText_Sensor.getText().toString();
mSysChLab.mSysChs.get(num).Unit=mEditText_Unit.getText().toString();
mSysChLab.mSysChs.get(num).Type=Integer.valueOf(mEditText_Type.getText().toString());
mSysChLab.mSysChs.get(num).K=Double.valueOf(mEditText_K.getText().toString());
mSysChLab.mSysChs.get(num).B=Double.valueOf(mEditText_B.getText().toString());
mSysChLab.mSysChs.get(num).isChecked=mCheckBox.isChecked();
mSysChLab.saveSysChs();
}
});
//返回按钮的监听器
mButton_return.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent mIntent = new Intent();
setResult(1,mIntent);
Intent i = new Intent();
i.setClass(ConfigureActivity.this, MainActivity.class);
i.putExtra("ip", IP);
i.putExtra("port", Port);
startActivity(i);
finish();
}
});
mySpinner.setPrompt( "通道号" );
//第二步:为下拉列表定义一个适配器,这里就用到里前面定义的list。
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list);
//第三步:为适配器设置下拉列表下拉时的菜单样式。
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//第四步:将适配器添加到下拉列表上
mySpinner.setAdapter(adapter);
//第五步:为下拉列表设置各种事件的响应,这个事响应菜单被选中
mySpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
num=arg2;
/* 将所选mySpinner 的值带入myTextView 中*/
mEditText_Sensor.setText(mSysChLab.mSysChs.get(arg2).Sensor);
mEditText_Unit.setText(mSysChLab.mSysChs.get(arg2).Unit);
mEditText_Type.setText(String.valueOf(mSysChLab.mSysChs.get(arg2).Type));
mEditText_K.setText(String.valueOf(mSysChLab.mSysChs.get(arg2).K));
mEditText_B.setText(String.valueOf(mSysChLab.mSysChs.get(arg2).B));
mCheckBox.setChecked(mSysChLab.mSysChs.get(arg2).isChecked);
/* 将mySpinner 显示*/
arg0.setVisibility(View.VISIBLE);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
arg0.setVisibility(View.VISIBLE);
}
});
/*下拉菜单弹出的内容选项触屏事件处理*/
mySpinner.setOnTouchListener(new Spinner.OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
/**
*
*/
return false;
}
});
/*下拉菜单弹出的内容选项焦点改变事件处理*/
mySpinner.setOnFocusChangeListener(new Spinner.OnFocusChangeListener(){
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
}
});
}
}
6、AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客)
《Android编程权威指南》之学习心得与笔记.by 2015.1.27
更多推荐
所有评论(0)