Android面试简录——文件存储

作者: nancymi | 来源:发表于2015-04-09 11:18 被阅读863次

    * SharedPreferences

    • 请描述Android SDK支持哪些文件存储技术?
      1.SharedPreferences保存key-value类型的数据
      2.流文件存储(openFileOutput/openFileInput或FileInputStream/FileOutputStream)
      3.XML半结构化存储
      4.用JSON保存数组和对象
      5.用数据库保存结构化数据
      6.用第三方的面向对象数据库直接保存Java对象

    • 如何使用SharedPreferences存取key-value类型的数据?
      1.Context.getSharedPreferences(参数1:存储key-value的文件名称,...) -> SharedPreferences对象
      2.SharedPreferences.edit -> SharedPreferences.Editor对象
      3.SharedPreferences.Editor.putXxx() -> 保存key-value对
      4.SharedPreferences.Editor.commit -> 提交key-value对
      从survey.xml文件中读取key-value对:
      String PREFERENCE_NAME = "survey";
      SharedPreferences sharedPreferences = getSharedPreferences(
      PREFERENCE_NAME, Activity.MODE_PRIVATE);
      etName.setText(sharedPreferences.getString("name", ""));
      etHabit.setText(sharedPreferences.getString("habit", ""));
      cbEompanyType.check(sharedPreferences.getInt("companyTypeId", ""));
      cbEmployee.setChecked(sharedPreferences.getBoolean("employee", false));
      rgCompanyType.check(sharedPreferences.getInt("companyTypeId", -1));
      向survey.xml文件中写入key-value对:
      SharedPreferences mySharedPreferences = getSharedPreferences(
      PREFERENCE_NAME, Activity.MODE_PRIVATE);
      SharedPreferences.Editor editor = mySharedPreferences.edit();
      editor.putString("name", "bill");
      editor.putString("habit", "swimming");
      editor.putBoolean("employee", true);
      editor.putInt("companyTypeId", 1);
      editor.edit();

    • 用SharedPreferences保存的数据文件放在哪个目录中?怎样不使用SharePreferences访问这些文件?
      存储路径:/data/data/packagename/shared_prefs.
      只能使用文件流读写SharedPreferences数据文件。
      String path = android.os.Environment.getDataDirectory().getAboslutePath()
      + "/data/" + getPackageName() + "/shared_prefs/abc.xml";
      try {
      BufferedReader br = new BufferedReader(
      new InputStreamReader(
      new FileInputStream(path)));
      Toast.makeText(this, br.readLine(), Toast.LENGTH_LONG);
      fis.close();
      } catch (Exception e) {

      }
      
    • SharedPreferences怎样把数据文件存储到sd卡上?
      SharedPreference原则上只能保存在当前应用程序私有的shared_prefs目录中,不过可以利用反射技术改变系统内定的文件保存路径。
      try {
      Field field = ContextWrapper.class.getDeclaredField("mBase");
      field.setAccessible(true);
      Object obj = field.get(this);
      field = obj.getClass().getDeclaredField("mPreferencesDir");
      field.setAccessible(true);
      File file = new File("/sdcard/");
      field.set(obj, file);
      SharedPreferences mySharedPreferences = getSharedPreferences("config", Activity.MODE_PRIVATE);
      SharedPreferences.Editor editor = mySharedPreferences.edit();
      editor.putString("name", "nancy");
      editor.commit();
      } catch (Exception e) { }

    • SharedPreferences文件可以保存图像数据吗?
      将图像转换成字符串再保存。采用Base64将二进制数据转换成字符串的编码。
      SharedPreferences sharedPreferences = getSharedPreferences("base64", Activity.MODE_PRIVATE);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ((BitmapDrawable) imageView.getDrawable()).getBitmap().compress(CompressFormat.JPEG, 50, baos);
      String imageBase64 = new String(Base64.encodeBase64(baos.toByteArray()));
      SharedPreferences.Editor editor = SharedPreferences.edit();
      editor.putString("productImage", imageBase64);
      editor.commit();
      读取:
      String imageBase64 = sharedPreferences.getString("productImage", "");
      base64Bytes = Base64.decodeBase64(imageBase64.getBytes());
      bais = new ByteArrayInputStream(base64Bytes);
      imageView.setImageDrawable(Drawable.createFromStream(bais, "product_image"));

    【拓展】在SharedPreferences中存取可序列化对象。
    序列化对象类:
    public class Product implements Serializable {
    private String name;
    private String id;
    private String price;
    //...
    }
    保存:
    Product product = new Product();
    product.setId(1234);
    product.setName("nancy");
    product.setPrice("9999");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.setObject(product);
    SharedPreferences sharedPreferences = getSharedPreferences("Product", Activity.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    String productBase64 = new String(Base64.encodeBase64(baos.toByteArray()));
    editor.putString("product", productBase64);
    editor.commit();
    读取:
    String productBase64 = sharedPreferences.getString("product", "");
    byte[] base64Bytes = Base64.decodeBase64(productBase64.getBytes());
    ByteArrayInputStream bais = new ByteArrayInputStream(base64Bytes);
    ObjectInputStream ois = new ObjectInputStream(bais);
    Product product = (Product) ois.readObject();

    • 如何通过PreferenceActivity类实现一个设置页面?
      通过xml配置文件来描述设置界面的设置项,系统会自动保存当前设置项的最后状态。
      常用设置项:
      1.CheckBoxPreference:创建CheckBox标签
      2.EditTextPreference:弹出带EditText的对话框
      3.ListPreference:弹出带ListView的对话框
      res/xml目录下的preference_setting文件:
      <?xml version="1.0" encoding="utf-8"?>
      <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      <PreferenceCategory android:title="我的位置源">
      <CheckBoxPreference android:key="wireless_network"
      android:title="使用无线网络"
      android:summary="使用无线网络查看应用程序的位置" />
      <CheckBoxPreference android:key="gps_satellite_setting"
      android:title="启用卫星定位"
      android:summary="定位时,精确到街道级别" />
      </PreferenceCategory>
      <PreferenceCategory android:title="个人信息设置">
      <CheckBoxPreference android:key="yesno_save_individual_info"
      android:title="是否保存个人信息" />
      <EditTextPreference android:key="individual_name"
      android:title="姓名"
      android:summary="请输入真实姓名" />
      <PreferenceScreen android:key="other_individual_msg"
      android:title="其他信息"
      android:summary="是否工作、手机" >
      <CheckBoxPreference android:key="mobile"
      android:title="手机"
      android:summary="请输入真实的手机号" />
      <CheckBoxPreference android:key="is_an_employee"
      android:title="是否工作" />
      </PreferenceScreen>
      </PreferenceCategory>
      </PreferenceScreen>
      配置:
      addPreferencesFromResource(R.xml.preference_setting);

    【拓展】使用PreferenceActivity预定义组件布局界面应注意什么?
    1.一个设置界面对应一个<PreferenceScreen>标签
    2.<PreferenceCategory>表示一个设置分类,title属性表示分类名称
    3.设置项标签可以不属于任何设置分类
    4.嵌套<PreferenceScreen>,说明该设置页有一个子设置页
    5.android:key属性的值是保存在XML文件中的key-value的key
    6.android:title,android:summary表示设置项的标题和摘要

    • 请说出PreferenceActivity保存数据文件的路径,文件的命名规则,默认的文件名是否可以更改。
      默认保存路径:shared_prefs目录
      默认文件名:packagename_preferences.xml
      如果当前窗口属于net.blogjava.mobile包,则默认文件名为net.blogjava.mobile_packagename_preferences.xml
      修改默认的文件名:PreferenceManager.setSharedPreferencesName:
      getPreferenceManager().setSharedPreferencesName("setting");
    • 用PreferenceActivity实现一个设置界面,如果某一个设置项的复选框变化后要求设置另一个列表项的状态,应该如何做呢?
      覆盖PreferenceActivity.onPreferenceTreeClick方法:
      public boolean onPreferenceTreeOnClick(PreferenceScreen preferenceScreen, Preference preference) {
      if ("yesno_save_individual_info".equals(preference.getKey())) {
      findPreference("individual_name").setEnabled(
      !findPreference("individual_name").isEnabled());
      }
      return super.onPreferenceTreeOnClick(preferenceScreen, Preference);
      }

    * 流文件

    • Android SDK支持哪些获取文件输入输出流的方式?
      1.直接创建FileInputStream和FileOutputStream对象
      try {
      FileOutputStream fos = new FileOutputStream("/sdcard/record.txt");
      //写入内容
      fos.close();
      FileInputStream fis = new FileInputStream("/sdcard/record.txt");
      //读取内容
      fis.close();
      } catch (Exception e) { }
      2.使用Context.openFileOutput/Context.openFileInput方法
      try {
      OutputStream os = openFileOutput("file.txt", Activity.MODE_PRIVATE);
      //写入内容
      os.close();
      InputStream is = openFileInput("file.txt");
      is.close();
      } catch(Exception e) { }
    • 请说出Context.openFileOutput方法存储数据文件的路径
      /data/data/<package name>/files
    • 如何使用ImageView组件装载SD卡上的图像文件?
      ImageView imageView = (ImageView) findViewById(R.id.imageView);
      imageView.setImageDrawable(Drawable.createFromPath("/sdcard/face.png"));

    XML存储

    • Android SDK支持读取XML吗?
      只支持采用SAX技术读取XML。

    • 请描述SAX分析XML文档的过程
      SAX引擎需要处理5个分析点(分析事件):
      1.开始分析XML文件。DefaultHandler.startDocument,初始化工作。
      2.开始处理每一个XML元素。startElement,获得当前元素的名称、元素属性的相关信息。
      3.处理完一个XML元素。endElement,获得当前处理完的元素的全部信息。
      4.处理完XML文件。endDocument,非必需方法,收尾工作(释放资源等)。
      *6.读取字符分析点。最重要。保存SAX引擎读取的XML文件内容,就是保存XML元素的文本。

    • 将XML文件转换成对象。
      xml文件示例:
      <?xml version="1.0" encoding="utf-8"?>
      <products>
      <product>
      <id>10</id>
      <name>电脑</name>
      <price>2067.25</price>
      </product>
      <product>
      <id>20</id>
      <name>微波炉</name>
      <price>520</price>
      </product>
      </products>
      List<Product>对象
      package net.blogjava.mobile;

      public class Product
      {
          private int id;
          private String name;
          private float price;
          //...getter and setter
      }
      XML2Product类负责具体的转换工作:
      package net.blogjava.mobile;
      
      import java.util.ArrayList;
      import java.util.net;
      import org.xml.sax.Attributes;
      import org.xml.sax.SAXException;
      import org.xml.sax.helpers.DefaultHandler;
      
      public class XML2Product extenda DefaultHandler
      {
          private List<Product> products;
          private Product product;
          private StringBuffer buffer = new StringBuffer();
          public List<Product> getProducts()
          {
                  return products;
          }
      }
      
      @Override
      public void characters(char[] ch, int start, int length) throws SAXException
      {
              //将SAX引擎扫描到的内容保存在buffer变量中,并为endElement提供参数
          buffer.append(ch, start, length);
          super.characters(ch, start, length);
      }
      
      @Override
      public void endElement(String uri, String localName, String gName) throws SAXException
      {
          //SAX每分析完一个XML元素,将该元素的文本保存在Product对象的相应属性中
          super.endElement(uri, localName, gName);
      }
      
      @Override
      public void sartDocument() throws SAXException
      {
              //创建用于保存转换结果的List<Product>对象
          products = new ArrayList<Product>();
      }
      
      @Override
      public void startElement(String uri, String localName, String qName, Attributes attributes) thows SAXException
      {
          //SAX引擎分析到每一个<product>结点时,创建一个Product对象
          super.startElement(uri, localName, qName, attributes);
      }
      
    • 补充endElement和startElement中的代码。
      @Override
      public void endElement(String uri, String localName, String gName) throws SAXException
      {
      if (localName.equals("product"))
      {
      products.add(product);
      }
      else if (localName.equals("id"))
      {
      product.setId(Integer.parseInt(buffer.toString().trim()));
      buffer.setLength(0);
      }
      else if (localName.equals("name"))
      {
      product.setName(buffer.toString().trim());
      buffer.setLength(0);
      }
      else if (localName.equals("price"))
      {
      product.setPrice(Float.parseFloat(buffer.toString().trim()));
      buffer.setLength(0);
      }
      super.endElement(uri, localName, gName);
      }
      @Override
      public void startElement(String uri, String localName, String qName, Attributes attributes) thows SAXException
      {
      if (localName.equals("product"))
      {
      product = new Product();
      }
      super.startElement(uri, localName, qName, attributes);
      }

    • 写出利用XML2Product类将products.xml文件的内容转换成List<Product>对象的Java代码。
      FileInputStream fis = new FileInputStream("/sdcard/products.xml");
      XML2Product xml2Product = new XML2Product();
      android.util.Xml.parse(fis, Xml.Encoding.UTF_8, xml2Product);
      List<Product> products = xml2Product.getProducts();


    JSON存储

    • 请描述JSON文档的格式
      使用字符串形式保存数组和对象属性值。
      数组使用'[]',对象使用'{}'。

    • 请解析JSON格式文档的Java代码,并输出到LogCat视图中。
      [{'name':'地球', 'satellite_count':'1', 'satellite_names':'moon'},{'name':'火星', 'satellite_count':'2', 'satellite_names':'Phobos, Deimos'}]
      try
      {
      String json = "[{'name':'地球', 'satellite_count':'1', 'satellite_names':'moon'},{'name':'火星', 'satellite_count':'2', 'satellite_names':'Phobos, Deimos'}]";
      JSONArray jsonArray = new JSONArray(json);
      for (int i = 0; i < jsonArray.length(); i ++)
      {
      String s = String.valueOf(jsonArray.get(i));
      JSONObject jsonObject = new JSONObject(s);
      Log.d("name", String.valueOf(jsonObject.get("name")));
      Log.d("satellite_count", String.valueOf(jsonObject.get("satellite_count")));
      if (jsonObject.has("satellite_names"))
      {
      Log.d("satellite_names", String.valueOf(jsonObject.get("satellite_names")));
      }
      }
      }
      catch (Exception e)
      {

      }
      

    相关文章

      网友评论

      本文标题:Android面试简录——文件存储

      本文链接:https://www.haomeiwen.com/subject/hfpzxttx.html