这是过年回来后第一个周末,心血来潮想复习一下java的知识 然后就有了这篇文章。
为什么写这篇文章呢说起来有点尴尬,对于读取写入这个操作我竟然没写出来,俗话说的好,“温故而知新”在这里强调一下温习的好处,希望各位也能在空闲时间内温习一下以前的知识。
其实我在写的过程中呢遇到很多问题,最终呢也是通过google解决了,其实我一直有一个疑问有的博客他是写的东西是错误的,导致我们找不到正确的解决方法,这是我一直疑惑的一点。话不多说来看一下我们今天的内容。
在这里说明一下今天这篇文章主要讲的是data/data/.../files下面文件的读取、写入
最后呢,我会把我写的代码贴到最下面直接复制就可以使用。
在这里呢是两个Button按钮:
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.output: //写入
writeSaveFile("com.baidu.calable","atcivity");
break;
case R.id.input: //读取
String pathname = "/data/data/com.seclab.recyclerviewmodule/files/Batch_Attack";
readSaveFile(pathname);
}
}
看以下代码我都有详细的注释让刚入门的胞友们更容易阅读
//写入文件中
private void writeSaveFile(String packageName, String component) {
FileOutputStream web_other = null;
try {
/**
* 在这里使用了StringBuilder为什么使用它感兴趣的小伙伴可以去搜索一下
* String、StringBuffer、以及StringBuilder的区别 --java的内容
*/
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(packageName + ";" + component+"\t\n");
//创建一个文件 第二次写入不会创建新的文件会直接追加到第一次写入内容的末尾
web_other = this.openFileOutput("Batch_Attack", Context.MODE_APPEND);
web_other.write(stringBuilder.toString().getBytes());
} catch (FileNotFoundException e) {
//按照编码规范的话捕获异常这里一般不会将错误信息就这么显示出来 如果有兴趣的小伙伴可以去找一篇编码规范一般都有
e.printStackTrace();
} catch (IOException e) {
//这里也是
e.printStackTrace();
} finally {
//这里是判断流然后才关闭 --编码规范中可以找到
if (web_other != null) {
try {
web_other.close();
Log.d("xxx","成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这个方法就是将内容写入到文件中。
这个方法呢不用判断这个文件是否存在 如果不存在则创建 存在则将内容追加到末尾
其实还有一种是需要存入一次数据就要创建一个文件这样的需求我还是写出来。
由于是写的时候没考虑到这个分析的可能没有特别的详细 但是不耽误使用
而且这段代码再最后总结的时候我是没有贴出来的。
存入一次创建一次一般都是比较独立的内容比如说是app崩溃收集起来的日志。
直接写在初始化中就可以
private Map<String, String> info = new HashMap<>(); 用来存放手机的信息
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
private FileOutputStream mFos;
// 收集设备参数信息 这个方法不是很重要他就是你要写进文件中的内容
collectDeviceInfo(mContext); //mContext是上下文
//写入文件中
saveCrashInfo2File(ex); //ex是收集到的错误信息
public void collectDeviceInfo(Context context) {
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null ? "null"
: pi.versionName;
String versionCode = Integer.toString(pi.versionCode);
info.put("versionName", versionName);
info.put("versionCode", versionCode);
}
} catch (PackageManager.NameNotFoundException e) {
LogUtils.e(TAG,e.toString());
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
info.put(field.getName(), field.get(field).toString());
} catch (IllegalArgumentException e) {
LogUtils.e(TAG,e.toString());
} catch (IllegalAccessException e) {
LogUtils.e(TAG,e.toString());
}
}
}
//存一次数据就创建一个文件 重点在这个方法
private String saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
//循环添加内容到StringBuffer
for (Map.Entry<String, String> entry : info.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
String result = writer.toString();
sb.append(result);
long timestamp = System.currentTimeMillis();
String time = format.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
try {
//每次存储数据都要重新创建文件
File filesDir = mContext.getFilesDir();
mFos= new FileOutputStream(filesDir + "/" + fileName);
mFos.write(sb.toString().getBytes());
mFos.flush();
} catch (IOException e) {
LogUtils.e(TAG,e.toString());
}finally {
try {
if (pw!=null){
pw.close();
}
if (mFos!=null){
mFos.close();
}
} catch (Exception e) {
LogUtils.e(TAG,e.toString());
}
}
return fileName;
}
这个方法就是读取文件中的内容
//读取data/data下文件
private void readSaveFile(String filename) {
FileInputStream inputStream;
try {
File file = new File(filename);
inputStream = new FileInputStream(file);
byte temp[] = new byte[1024];
StringBuilder sb = new StringBuilder("");
int len = 0;
while ((len = inputStream.read(temp)) > 0){
sb.append(new String(temp, 0, len));
}
Log.d("msg", "readSaveFile: \n" + sb.toString());
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
这样就可以读取到文件中的内容了。
File file = new File(filename);
inputStream = new FileInputStream(file);
在这里也有一个点让我找了好久上面这两句话 我本来用的是 inputStream = openFileInput(filename);
他会抛出一个异常
java.lang.IllegalArgumentException:
File /data/data/com.seclab.recyclerviewmodule/files/Batch_Attack contains a path separator
问题吗我找到了但是忘记是怎么回事了,嘿嘿~ 如果遇到这个问题直接换成上面两句话就可以。
看一下效果吧
上面就是控制台打印的信息 我点击了三次写入 然后我读取出来这么多次是因为我以前添加了
贴上我写的代码
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FileIOActivity">
<Button
android:id="@+id/input"
android:text="读取"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/output"
android:text="写入"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
package com.seclab.recyclerviewmodule;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class FileIOActivity extends AppCompatActivity implements View.OnClickListener {
// 申请权限的requestCode
private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_i_o);
Button input = findViewById(R.id.input);
Button outPut = findViewById(R.id.output);
input.setOnClickListener(this);
outPut.setOnClickListener(this);
// 动态获取读写权限
checkPermissionReadAndWrite();
}
/**
*
* 动态获取读写权限。
*/
private void checkPermissionReadAndWrite() {
int hasReadPermission = ContextCompat.checkSelfPermission(getApplication(),
Manifest.permission.READ_EXTERNAL_STORAGE);
int hasWritePermission = ContextCompat.checkSelfPermission(getApplication(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasReadPermission == PackageManager.PERMISSION_GRANTED&&hasWritePermission==PackageManager.PERMISSION_GRANTED) {
//获取权限之后的操作
} else {
//没有权限,申请权限。
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_CAMERA_REQUEST_CODE);
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.output:
writeSaveFile("com.baidu.calable","atcivity");
break;
case R.id.input:
String pathname = "/data/data/com.seclab.recyclerviewmodule/files/Batch_Attack";
readSaveFile(pathname);
}
}
//写入文件中
private void writeSaveFile(String packageName, String component) {
FileOutputStream web_other = null;
try {
/**
* 在这里使用了StringBuilder为什么使用它感兴趣的小伙伴可以去搜索一下
* String、StringBuffer、以及StringBuilder的区别 --java的内容
*/
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(packageName + ";" + component+"\t\n");
//创建一个文件 第二次写入不会创建新的文件会直接追加到第一次写入内容的末尾
web_other = this.openFileOutput("Batch_Attack", Context.MODE_APPEND);
web_other.write(stringBuilder.toString().getBytes());
} catch (FileNotFoundException e) {
//按照编码规范的话捕获异常这里一般不会将错误信息就这么显示出来 如果有兴趣的小伙伴可以去找一篇编码规范一般都有
e.printStackTrace();
} catch (IOException e) {
//这里也是
e.printStackTrace();
} finally {
//这里是判断流然后才关闭 --编码规范中可以找到
if (web_other != null) {
try {
web_other.close();
Log.d("xxx","成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//读取data/data下文件
private void readSaveFile(String filename) {
FileInputStream inputStream;
try {
File file = new File(filename);
inputStream = new FileInputStream(file);
byte temp[] = new byte[1024];
StringBuilder sb = new StringBuilder("");
int len = 0;
while ((len = inputStream.read(temp)) > 0){
sb.append(new String(temp, 0, len));
}
Log.d("msg", "readSaveFile: \n" + sb.toString());
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面有一个动态申请的权限 如果不需要的话可以将这段代码删除 当时我以为是权限的问题所以添加上了
好了,到这里就结束了 其中有三个方法是小扩展
collectDeviceInfo(mContext);
saveCrashInfo2File(ex);
作用存储一次数据就要根据时间戳创建一次文件
上面这两个方法没有贴出来因为没办法贴出来 谅解一下 但是可以使用
还有一个动态申请权限的方法 直接可以在onCreate方法中使用
checkPermissionReadAndWrite()动态获取读写权限
看着代码挺多其实没有多少 重要的有两个方法 读取和写入 扩展的有三个方法
慢慢看的话用不了10分钟就可以看完 而且都是可以进行复制的。
如果有什么不懂的地方大家可以给我留言或者加我QQ137478494
[https://blog.csdn.net/Zadarrien_China/article/details/55226068](https://blog.csdn.net/Zadarrien_China/article/details/55226068)
大家下期再见咯!给大家推荐几篇文章
https://blog.csdn.net/Zadarrien_China/article/details/55226068
https://blog.csdn.net/ztp800201/article/details/7322110