首页 > 技术文章 > 第三章 数据存储到应用的目录下、文件查看 1.1

EndlessShw 2021-07-20 13:27 原文

1. 文件内容的保存看代码,其中id在xml中已经定义

  1 package com.example.qq_login_demo;
  2 
  3 import androidx.appcompat.app.AppCompatActivity;
  4 
  5 import android.os.Bundle;
  6 import android.speech.tts.TextToSpeech;
  7 import android.text.TextUtils;
  8 import android.util.Log;
  9 import android.view.View;
 10 import android.widget.Button;
 11 import android.widget.EditText;
 12 import android.widget.Toast;
 13 
 14 import java.io.BufferedReader;
 15 import java.io.File;
 16 import java.io.FileInputStream;
 17 import java.io.FileNotFoundException;
 18 import java.io.FileOutputStream;
 19 import java.io.InputStreamReader;
 20 
 21 public class MainActivity extends AppCompatActivity {
 22 
 23     private static final String TAG = "MainActivity";
 24     private EditText mUsername;
 25     private EditText mPassword;
 26     private Button mLogin;
 27 
 28     @Override
 29     protected void onCreate(Bundle savedInstanceState) {
 30         super.onCreate(savedInstanceState);
 31         setContentView(R.layout.qq_ui_login_layout);
 32 
 33         // 第一步,找到控件
 34         initview();
 35 
 36         // 第二步,给登录按钮设置点击事件
 37         initListener();
 38     }
 39 
 40     /**
 41      * 这个方法,我们用来找到对应的控件
 42      */
 43     private void initview(){
 44         mUsername = (EditText) this.findViewById(R.id.Username);
 45         mPassword = (EditText) this.findViewById(R.id.Password);
 46         mLogin = (Button) this.findViewById(R.id.Login);
 47 
 48     }
 49 
 50     /**
 51      * 这个方法,我们用来设置监听事件
 52      */
 53     private void initListener(){
 54         mLogin.setOnClickListener(new View.OnClickListener() {
 55             @Override
 56             public void onClick(View v) {
 57                 // 当方法的内容比较长时,可以在方法外写,有助于代码阅读
 58                 // 写完方法名后,alt + enter 在外层定义函数
 59                 handlerLoginEvent(v);
 60             }
 61         });
 62     }
 63 
 64     @Override
 65     protected void onResume() {
 66         super.onResume();
 67 //        File filesDir = this.getFilesDir();
 68 //        File saveFile = new File(filesDir, "info.text");
 69         // 可以使用以下的方法来获取数据
 70         try {
 71             FileInputStream fileInputStream = this.openFileInput("info.text");
 72             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
 73             String info = bufferedReader.readLine();
 74 
 75             // fout.write((username + ": " + password).getBytes());
 76             // 这行代码是之前使用的保存形式,也就是说拿到数据以后,要对数据进行切割
 77             String[] splits = info.split(": ");
 78             String username = splits[0];
 79             String password = splits[1];
 80 
 81             // 回显数据
 82             mPassword.setText(password);
 83             mUsername.setText(username);
 84         } catch (Exception e) {
 85             e.printStackTrace();
 86         }
 87     }
 88 
 89     /**
 90      * 处理按钮事件
 91      */
 92     private void handlerLoginEvent(View v) {
 93         // 第三步,取出EditText内的内容,即输入的账号和密码
 94         // 账号
 95         String password = mPassword.getText().toString();
 96         String username = mUsername.getText().toString();
 97 
 98         // 对账号密码进行检查,在实际开发中对用户的账号和密码进行数据校验
 99 
100         // 账号密码进行判空
101         // 第一种办法:
102 //        if(username.length() == 0){
103 //            // 账号长度为空
104 //            // 这里的this向上溯源,继承Context类,指代当前的activity
105 //            // https://www.iteye.com/blog/cai-bird-1245146 toast的使用详解
106 //            Toast.makeText(this, "账号不可以为空", Toast.LENGTH_SHORT).show();
107 //            return;
108 //        }
109 //        else if (password.length() == 0) {
110 //            Toast.makeText(this, "密码不可以为空", Toast.LENGTH_SHORT).show();
111 //            return;
112 //        }
113 
114         // 第二种方法:
115         // https://www.jianshu.com/p/4095639631aa TextUtil工具类的使用
116         if (TextUtils.isEmpty(username)) {
117             // 账号为空
118             Toast.makeText(this, "账号不能为空", Toast.LENGTH_SHORT).show();
119             return;
120         }
121         else if(TextUtils.isEmpty(password)){
122             // 密码为空
123             Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show();
124             return;
125         }
126 
127         // 把账号和密码保存起来:
128         saveUserInfo(password, username);
129 }
130 
131     private void saveUserInfo(String password, String username) {
132         Log.d(TAG, "保存用户信息");
133         /**
134          * 直接写一个文件名的时候,去写文件,爆出的异常是read-only
135          * 在Android系统中,每一个应用就是一个用户,每一个用户的权限是特定的,不可以操作其他应用的内容,所以需要特地的文件路径以及要提前创建文件
136          * 以"/"为根目录
137          */
138         File file = new File("/data/data/com.example.qq_login_demo/info.text");
139 
140         // 实际情况下,该目录比较长,不实用,所以用以下方法来解决:
141         File filesDir = this.getFilesDir();
142         Log.d(TAG, "files dir == " + filesDir.toString());
143         // 输出的结果为: /data/user/0/com.example.qq_login_demo/files
144         // 也就是说,getFilesDir()这个方法它拿到的路径为/data/data/包名/files这个路径(即新建一个files文件夹
145         // 改进的方法为:
146         File saveFile = new File(filesDir, "info.text");
147         Log.d(TAG, "saveFile == " + saveFile.toString());
148         file = saveFile;
149         // 此时这里的saveFile就是/data/data/com.example.qq_login_demo/files/info.text
150 
151         // 相应的,cache也有相应的路径,结果为: /data/user/0/com.example.qq_login_demo/cache
152         File cacheDir = this.getCacheDir();
153         Log.d(TAG, "cache dir == " + cacheDir.toString());
154 
155         /**
156          * /data/user/0/com.example.qq_login_demo/files
157          * 上面这个路径为保存文件路径,我们可以用代码删除,也可以通过设置里的应用列表里的选项进行清理
158          * /data/user/0/com.example.qq_login_demo/cache
159          * 上面这个为缓存路径,用于保存缓存文件,该目录下的文件,会由系统根据存储情况进行清理
160          */
161 
162         try {
163             // 如果文件不存在,则创建文件
164             if(!file.exists()){
165                 file.createNewFile();
166             }
167             FileOutputStream fout = new FileOutputStream(file);
168             // 以特定的格式来存储账号密码
169             // 格式: username: password
170             fout.write((username + ": " + password).getBytes());
171             fout.close();
172             Toast.makeText(this, "数据保存成功", Toast.LENGTH_SHORT).show();
173         } catch (Exception e) {
174             e.printStackTrace();
175         }
176     }
177 }

 

2. layout定义

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:background="@mipmap/img_20191105_072932"
 7     android:orientation="vertical"
 8     >
 9 
10     <LinearLayout
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content"
13         android:layout_marginTop="50dp"
14         android:padding="30dp"
15         android:orientation="vertical">
16         <TextView
17             android:drawableLeft="@mipmap/ic_launcher"
18             android:layout_width="wrap_content"
19             android:layout_height="wrap_content"
20             android:textSize="40sp"
21             android:text="QQ"/>
22 
23         <EditText
24             android:id="@+id/Username"
25             android:layout_width="match_parent"
26             android:layout_height="match_parent"
27             android:hint="QQ号码/手机号/邮箱"
28             android:textColorHint="@color/white" />
29 
30         <EditText
31             android:id="@+id/Password"
32             android:inputType="textPassword"
33             android:layout_marginTop="30dp"
34             android:layout_width="match_parent"
35             android:hint="密码"
36             android:textColorHint="@color/white"
37             android:layout_height="match_parent"/>
38 
39         <Button
40             android:id="@+id/Login"
41             android:layout_width="match_parent"
42             android:layout_height="wrap_content"
43             android:text="登录"
44             android:textSize="20sp"
45             android:background="#00aaff"/>
46 
47         <RelativeLayout
48             android:layout_width="match_parent"
49             android:layout_height="wrap_content">
50 
51             <TextView
52                 android:layout_width="wrap_content"
53                 android:layout_height="wrap_content"
54                 android:text="忘记密码"
55                 android:textColor="#00aaff"
56                 android:textSize="16sp"/>
57 
58             <TextView
59                 android:layout_width="wrap_content"
60                 android:layout_height="wrap_content"
61                 android:text="新用户注册"
62                 android:textColor="#00aaff"
63                 android:textSize="16sp"
64                 android:layout_alignParentRight="true"/>
65 
66         </RelativeLayout>
67 
68     </LinearLayout>
69 
70     <TextView
71         android:layout_width="wrap_content"
72         android:layout_height="wrap_content"
73         android:layout_alignParentBottom="true"
74         android:layout_centerHorizontal="true"
75         android:layout_marginBottom="20dp"
76         android:text="登录即代表阅读并同意服务条款"
77         android:textColor="#00aaff"
78         android:textSize="20sp"
79         android:id="@+id/a">
80     </TextView>
81 </RelativeLayout>

 

3. 文件内容查看

  第一种方法:

     在dbs shell中进入到所创建文件的包中。本例子的路径为:

    /data/data/com.example.qq_login_demo

    包的名字可以在manifests文件夹下的AndroidManifest.xml中查看

  

  第二种方法:

    view--Tool Windows--Device File Explorer中,将模拟器中的文件导出查看

推荐阅读