本章学习到了数据的存储,其包含了文件存储、SharedPreferences、SQLite数据库、ContentProvider、网络存储的内容,而本案例则是对于文件存储的学习,创建一个登录界面,用户输入账号密码点击登录会保存txt文件到内部存储中(不是sd卡外部存储,存储路径为data/data/包名),先看一下效果图(还是一样,讲解将会在后续补充(一般已经写在了注释中),如有问题,欢迎评论)

进入页面会自动获取txt文件中的内容

android studio 保存文件 sd卡 android studio如何保存程序_java

 以下是xml代码,(我使用了一个圆形图片的一个第三方库,可以更换成自己的图片使用最简单的ImageView)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E6E6E6"
    android:orientation="vertical"
    android:padding="10dp">

    <com.makeramen.roundedimageview.RoundedImageView
        android:layout_marginTop="100dp"
        android:id="@+id/imageView1"
        android:layout_width="140dp"
        android:layout_height="140dp"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal"
        android:scaleType="fitCenter"
        android:src="@drawable/a111"
        app:riv_border_color="#333333"
        app:riv_border_width="2dip"
        app:riv_corner_radius="30dip"
        app:riv_mutate_background="true"
        app:riv_oval="true"
        />
    <!--    app:riv_tile_mode="repeat"使用  会覆盖-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:background="@android:color/white"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="账号:"
            android:textColor="#000"
            android:textSize="20sp" />
        <EditText

            android:id="@+id/et_account"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:background="@null"
            android:padding="10dp" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@android:color/white"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/tv_password"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="密码:"
            android:textColor="#000"
            android:textSize="20sp" />
        <EditText
            android:id="@+id/et_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:background="@null"
            android:inputType="textPassword"
            android:padding="10dp" />
    </LinearLayout>
  

    <Button
        android:onClick="function"
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"
        android:background="#3C8DC4"
        android:text="登录"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>

如果你要使用和我一样的圆角图片,可以在build.gradle中引入依赖:

implementation 'com.makeramen:roundedimageview:2.3.0'

ok,以下是一个自定义的工具类FileSaveQQ

import android.content.Context;
import android.view.View;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class FileSaveQQ {
    //保存用户信息方法
    //参数:  上下文  账号  密码
    public static boolean saveUserInfo(Context context, String account, String password){
        //使用(文件)输出流
        FileOutputStream fos=null;
        try {
            //获取文件的输出流对象  openFileOutput参数filename、mode 文件名与模式,这里的模式为私有数据
            fos=context.openFileOutput("data.txt",Context.MODE_PRIVATE);
            //将数据转换为字节码的形式写入data.txt文件中
            //write(byte b[])
            //存储格式是 账号:密码
            fos.write((account+":"+password).getBytes());
            return true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return  false;
        }finally {
            //在finally进行关闭流操作
            try {
                //不为空则关闭
                if (fos!=null){
                    fos.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    //从文件获取存储的用户数据
    //参数 上下文 返回类型为Map键值对类型
    public static Map<String,String> getUserInfo(Context context){
        //设置一个空的字符串 用来获取数据
        String content="";
        //文件的输入流对象
        FileInputStream fis=null;
        try {
            //获取文件输入流  参数为filename 即文件的名称
            fis=context.openFileInput("data.txt");
            //定义一个byte[]对象  并将输入流对象的数据转换为字节码的形式
            //返回字节的预估值fis.available(),简单的理解为长度
            byte[]buffer=new byte[fis.available()];
            //通过read方法读取字节码的数据
            fis.read(buffer);
            //将获取的字节码转换为字符串
            content=new String(buffer);
            //定义一个hashmap键值对类型用来存储账号和密码
            Map<String,String> userMap=new HashMap<String,String>();
            //将字符串以“:”分隔后获取分隔后的字符串数组
            String[]infos=content.split(":");
            //将数组的第一个数据,即用户的账号存储在userMap中
            userMap.put("account",infos[0]);
            //将数组的第二个数据,即用户的密码存储在userMap中
            userMap.put("password",infos[1]);
            return userMap;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        finally {
            //在finally进行关闭流操作
            try {
                if(fis!=null){
                    fis.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
}

以下是Activity的逻辑代码

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.Map;

public class MainActivity54 extends AppCompatActivity {
    //页面的控件
private EditText et_account,et_password;
private Button btn_login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main54);
        initView();//用于绑定控件以及按钮的点击事件设置
        //用于进入Activity时,获取文件数据并判断不为空的话设置EditText中去
        Map<String,String> userInfo=FileSaveQQ.getUserInfo(MainActivity54.this);
        if(userInfo!=null){
            //设置账号数据
            et_account.setText(userInfo.get("account"));
            //设置密码数据
            et_password.setText(userInfo.get("password"));
        }
    }
    //绑定控件以及点击事件绑定
    private void initView(){
        et_account=findViewById(R.id.et_account);
        et_password=findViewById(R.id.et_password);
        btn_login=findViewById(R.id.btn_login);
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取两个EditText的数据并使用trim来去掉首尾空
                String account=et_account.getText().toString().trim();
                String password=et_password.getText().toString().trim();
                //判断输入的字符串是否为空 空则显示对应提示
                if(TextUtils.isEmpty(account)){
                    Toast.makeText(MainActivity54.this,"请输入QQ账号",Toast.LENGTH_SHORT).show();
                    return;
                }
                if(TextUtils.isEmpty(password)){
                    Toast.makeText(MainActivity54.this,"请输入QQ密码",Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(MainActivity54.this,"登陆成功",Toast.LENGTH_SHORT).show();
                //不为空,执行工具类FileSaveQQ的saveUserInfo方法,传递上下文、账号、密码
                boolean isSaveSuccess=FileSaveQQ.saveUserInfo(MainActivity54.this,account,password);
                //判断是否保存成功,并提示
                if(isSaveSuccess){
                    Toast.makeText(MainActivity54.this,"保存成功",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(MainActivity54.this,"保存失败",Toast.LENGTH_SHORT).show();
                }
                return;
            }
        });
    }
}

最后你可以在data/data/包名下看到txt文件

android studio 保存文件 sd卡 android studio如何保存程序_android_02

若出现文件打不开等情况?

1. 文件保存操作保存的文件无法打开:命令行输入adb devices
如果提示adb不是内部或外部命令, 则将adb所在目录添加到path中, adb.exe文件位于sdk下的platform-tools目录中

2. 如果输入后提示 adb: unable to connect for root: device offline,
则终端中输入 step1: adb kill-server, step2: adb devices 。如不成功,重复 step1,step2多次。