1.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 读取文件
*/
public void readFile(View view) {// 很多初学者都会犯的错误
try {
FileInputStream fis = openFileInput("file.txt");
byte[] bytes = new byte[20];
fis.read(bytes);
System.out.println("content:" + new String(bytes));
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 写入文件
*/
public void writeFile(View view) {
// 创建一个文件,程序自身可以读写
try {
FileOutputStream fos = openFileOutput("file.txt", Context.MODE_PRIVATE);
fos.write("data".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.模仿QQ登入,记住用户是写入文件
package com.glsite.qqloging;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
public class MainActivity extends AppCompatActivity {
private EditText mEtnumber;
private EditText mEtpassword;
private CheckBox mMcbRemember;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1.找到界面上的控件
// 2.点击按钮,将用户输入的用户名和密码保存到文件当中
// 3.如果说下次启动app,那么就从文件当中读取出来显示到编辑框
mEtnumber = findViewById(R.id.et_qqnumber);//ctrl+alt+f
mEtpassword = findViewById(R.id.et_password);
mMcbRemember = findViewById(R.id.cb_remember);
restoreInfo();
}
/**
* 根据原来保存的文件信息,把QQ号码和密码信息显示到界面
*/
private void restoreInfo() {
File file = new File(this.getFilesDir(), "info.txt");
try {
if (file.exists()&&file.length()>0) {
FileInputStream fileInputStream = new FileInputStream(file);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String s = bufferedReader.readLine();
String[] split = s.split("##");
mEtnumber.setText(split[0]);
mEtpassword.setText(split[1]);
} else {
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 登录按钮的点击事件
*
* @param view
*/
public void login(View view) {
String qq = mEtnumber.getText().toString().trim();//str_t
String password = mEtpassword.getText().toString().trim();
// 判断是否需要记录用户名和密码
if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(password)){
Toast.makeText(this,"用户名或密码不能为空", Toast.LENGTH_SHORT).show();
return;
}else{
//模拟登入
if ("10000".equals(qq)&&"123456".equals(password)) {
//判断是否不需要记住用户名或密码
File file = new File(this.getFilesDir(), "info.txt");
//判断用户是否勾选了记住用户
if(mMcbRemember.isChecked()){
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
String info = qq + "##" +password;
fileOutputStream.write(info.getBytes());
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}else{
if (file.exists()) {
file.delete();//未勾选保存,删除保存的文件
}
}
Toast.makeText(this,"登入成功", Toast.LENGTH_SHORT).show();
/*Toast.makeText(this,this.getFilesDir().getAbsolutePath(), Toast.LENGTH_SHORT).show();*/
} else {
Toast.makeText(this,"登入失败", Toast.LENGTH_SHORT).show();
}
}
}
}
3.用户sd卡储存,注意需要配置权限,安卓6.0需要运行时权限
3.1运行时权限
package com.glsite.wriesd;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
/**
* @author Admin
* @version $Rev$
* @des ${TODO}
* @updateAuthor $Author$
* @updateDes ${TODO}
*/
public class BaseActivity extends AppCompatActivity {
//**************** Android M Permission (Android 6.0权限控制代码封装)
private int permissionRequestCode = 88;
private PermissionCallback permissionRunnable;
public interface PermissionCallback {
void hasPermission();
void noPermission();
}
/**
* Android M运行时权限请求封装
*
* @param permissionDes 权限描述
* @param runnable 请求权限回调
* @param permissions 请求的权限(数组类型),直接从Manifest中读取相应的值,比如Manifest.permission.WRITE_CONTACTS
*/
public void performCodeWithPermission(@NonNull String permissionDes, PermissionCallback runnable, @NonNull String... permissions) {
if (permissions == null || permissions.length == 0)
return;
// this.permissionrequestCode = requestCode;
this.permissionRunnable = runnable;
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) || checkPermissionGranted(permissions)) {
if (permissionRunnable != null) {
permissionRunnable.hasPermission();
permissionRunnable = null;
}
} else {
//permission has not been granted.
requestPermission(permissionDes, permissionRequestCode, permissions);
}
}
private boolean checkPermissionGranted(String[] permissions) {
boolean flag = true;
for (String p : permissions) {
if (ActivityCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) {
flag = false;
break;
}
}
return flag;
}
private void requestPermission(String permissionDes, final int requestCode, final String[] permissions) {
if (shouldShowRequestPermissionRationale(permissions)) {
/*1. 第一次请求权限时,用户拒绝了,下一次:shouldShowRequestPermissionRationale() 返回 true,应该显示一些为什么需要这个权限的说明
2.第二次请求权限时,用户拒绝了,并选择了“不在提醒”的选项时:shouldShowRequestPermissionRationale() 返回 false
3. 设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale() 返回 false*/
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example, if the request has been denied previously.
// Snackbar.make(getWindow().getDecorView(), requestName,
// Snackbar.LENGTH_INDEFINITE)
// .setAction(R.string.common_ok, new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// ActivityCompat.requestPermissions(BaseAppCompatActivity.this,
// permissions,
// requestCode);
// }
// })
// .show();
//如果用户之前拒绝过此权限,再提示一次准备授权相关权限
new AlertDialog.Builder(this)
.setTitle("提示")
.setMessage(permissionDes)
.setPositiveButton("授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
}
}).show();
} else {
// Contact permissions have not been granted yet. Request them directly.
ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);
}
}
private boolean shouldShowRequestPermissionRationale(String[] permissions) {
boolean flag = false;
for (String p : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, p)) {
flag = true;
break;
}
}
return flag;
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == permissionRequestCode) {
if (verifyPermissions(grantResults)) {
if (permissionRunnable != null) {
permissionRunnable.hasPermission();
permissionRunnable = null;
}
} else {
Toast.makeText(this, "暂无权限执行相关操作!", Toast.LENGTH_SHORT).show();
if (permissionRunnable != null) {
permissionRunnable.noPermission();
permissionRunnable = null;
}
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public boolean verifyPermissions(int[] grantResults) {
// At least one result must be checked.
if (grantResults.length < 1) {
return false;
}
// Verify that each required permission has been granted, otherwise return false.
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
//********************** END Android M Permission ****************************************
}
3.2
package com.glsite.wriesd;
import android.Manifest;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View view) {
performCodeWithPermission("写入文件权限", new PermissionCallback() {
@Override
public void hasPermission() {
//判断sd卡是否挂载
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(MainActivity.this, "sd卡已经挂载", Toast.LENGTH_SHORT).show();
File sdfile = Environment.getExternalStorageDirectory();
long freeSpace = sdfile.getFreeSpace();//获取储存空间
if (freeSpace > 5 * 1024 * 1024) {
File file = new File(sdfile, System.currentTimeMillis() + "hlw.3gp");
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] bytes = new byte[1024];
for (int i = 0; i < 5 * 1024; i++) {
fileOutputStream.write(bytes);
}
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(MainActivity.this, "内部空间不足", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(MainActivity.this, "没有挂载", Toast.LENGTH_SHORT).show();
}
}
@Override
public void noPermission() {
Toast.makeText(MainActivity.this,"用户未授权", Toast.LENGTH_SHORT).show();
}
}, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
3.3 配置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
4.权限机制
-rwxrw-r‐-1 root root 1213 Feb 2 09:39 abc
- 10个字符确定不同用户能对文件干什么
- 第一个字符代表文件(-)、目录(d),链接(l)
- 其余字符每3个一组(rwx),读(r)、写(w)、执行(x)
- 第一组rwx:文件所有者的权限是读、写和执行
- 第二组rw-:与文件所有者同一组的用户的权限是读、写但不能执行
- 第三组r--:不与文件所有者同组的其他用户的权限是读不能写和执行
也可用数字表示为:r=4,w=2,x=1 因此rwx=4+2+1=7
- 1 表示连接的文件数
- root 表示用户
- root表示用户所在的组
- 1213 表示文件大小(字节)
- Feb 2 09:39 表示最后修改日期
- abc 表示文件名
5.文件操作的两种模式
Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。