android 学习笔记2-logcat 内外部文件的存储 文件权限 xml读写

本文详细介绍了Android中logcat的使用,包括不同级别日志的输出和过滤。接着讲解了如何在内部存储中读写文件,区分了files和cache文件夹的区别。讨论了外部存储的访问权限,包括所需的权限声明和路径变化。此外,还提到了Toast的显示和文件访问权限的解析,以及使用SharedPreference和XML进行数据存储的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、logcat
    分5个等级,每个等级使用不同颜色
    verbose
debug
info
warn
error
    定义过滤器方便查看
    
    System.out.print输出的日志级别是info,tag是System.out
    Android提供的日志输出api
Log.v(TAG, "hello");
Log.d(TAG, "hello");
Log.i(TAG, "hello");
Log.w(TAG, "hello");
Log.e(TAG, "hello");
        
        
2、在内部存储中写文件


    Ram内存:运行内存,相当于电脑的内存
    Rom内存:内部存储空间,相当于电脑的硬盘
    sd卡:外部存储空间,相当于电脑的移动硬盘
        
    所有安装至手机的应用都会在data/data目录下生成一个包名文件夹,这个文件夹就是内部存储的路径
    应用只能在自己的包名文件夹中读写文件
    例子:
   
        //返回一个File对象,封装的路径是data/data/com.example.test/files
        //File file = new File(getFilesDir(), "info.txt");
        
        //返回一个File对象,封装的路径是data/data/com.example.test/cache
        File file = new File(getCacheDir(), "info.txt");
        try {
            FileOutputStream fos = new FileOutputStream(file);
            //把账号密码写入本地文件
            fos.write((name + "--" + pass).getBytes());//将字符串转化为字节流写到文件中
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
3、在内部存储中读文件


    例子:
        private void readAccount() {
            //读取文件,回显数据,文件info.txt的内容是 test--123
            //File file = new File("data/data/com.example.test/info.txt");  //这个会保存在应用的目录files文件夹下,就算空间不够也不会删除,除非用户自己清理
            File file = new File(getFilesDir(), "info.txt");//这个会保存在应用的目录files文件夹下,就算空间不够也不会删除,除非用户自己清理
            //File file = new File(getCacheDir(), "info.txt");//这个会保存在应用的目录caches文件夹下,如果空间不够就会被清除掉
            if(file.exists()){//判断文件是否存在
                try {
                    FileInputStream fis = new FileInputStream(file);
                    //把字节流转换成字符流
                    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                    //读取文件中的文本
                    String text = br.readLine();
                    
                    String s[] = text.split("--");
                    
                    //给输入框设置文本
                    et_name.setText(s[0]);
                    et_pass.setText(s[1]);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }


        
4、Toast显示对话框:
    Toast t = Toast.makeText(this, "登录成功", 0);
    Toast t = Toast.makeText(MainActivity.this, "登录成功", 1);
    
    第一个参数是一个上下文,一个activity也是个上下文
    第三个参数只能是 0 或 1 (0显示3s  , 1显示 5s)
    
    
5、应用中的files文件夹和cache文件夹的区别:
    files文件夹下文件,就算空间不够也不会删除,除非用户自己清理
    caches文件夹下文件,如果空间不够就会被清除掉
    
    在系统管理应用界面的清除缓存,会清除cache文件夹下的东西,清除数据,会清除整个包名目录下的东西
    
6、在外部存储读写数据:
    android 2.2之前,sd卡路径:sdcard
    android 4.3之前,sd卡路径:mnt/sdcard
    android 4.3开始,sd卡路径:storage/sdcard
    
    File file = new File("sdcard/info.txt");
    
    写sd卡需要权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    读sd卡,在4.0之前不需要权限,4.0之后可以设置为需要
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        
        
    现在很多手机品牌会更改sd卡的路径 ,使用api获得sd卡的真实路径
    Environment.getExternalStorageDirectory()
    
    判断sd卡是否准备就绪
    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))//已挂载上了
    
    其他的读写方式和上面的内部存储一样的
    
    
7、导入android源码分析系统的应用(settings)
    导入eclipse查看有很多的红色警告,是因为系统应用访问的很多的API我们不能访问,所以会提示找不到类,但是我们只需要看怎么实现的,不需要编译。
    
    不能直接import 一个android工程,因为源码是一个android项目,但不是一个eclipse项目
    解决办法:
        在eclipse中 New  -- Other... -- Android -- Android Project from Existing Code
        显示创建了2个项目,我们只选择我们需要的项目
        
        
8、文件访问权限:
    在Android中,每一个应用是一个独立的用户
    drwxrwxrwx
        第1位:d表示文件夹,-表示文件
        第2-4位:rwx,表示这个文件的拥有者用户(owner)对该文件的权限,【例如我这个应用创建了这个文件,这个应用权限就是2-4位的权限】
        r:读
        w:写
        x:执行
        第5-7位:rwx,表示跟文件拥有者用户同组的用户(grouper)对该文件的权限,【默认两个应用不会是一个用户组的,可以手动设置2个应用为同一个用户组,主要是android自己的系统应用设置了,这个场景一般应用比较少】
        第8-10位:rwx,表示其他用户组的用户(other)对该文件的权限 【其他的应用】
    
        
    备注:可以创建一个所有用户都可以访问的文件,但是google现在不推荐这样做,会存在安全漏洞,已经被废弃掉了。建议使用ContentProvider 或BroadcastReviever替代。
        MODE_PRIVATE:-rw-rw----
        MODE_APPEND:-rw-rw----
        MODE_WORLD_WRITEABLE:-rw-rw--w-
        MODE_WORLD_READABLE:-rw-rw-r--


        FileOutputStream fos = openFileOutput("info.txt", MODE_WORLD_READABLE);
        FileOutputStream fos = openFileOutput("info.txt", MODE_WORLD_WRITEABLE | MODE_WORLD_READABLE);
fos.write("lalala".getBytes());
    
    
9、使用SharedPreference读写文件,是写到一个xml文件中的,比较适合存储零散的数据


        往SharedPreference里写数据
            //拿到一个SharedPreference对象
            SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);//这个是activity自带的一个API
            //拿到编辑器
            Editor ed = sp.edit();
            //写数据
            ed.putBoolean("name", name);
            ed.commit();


    从SharedPreference里取数据
SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
//从SharedPreference里取数据
String name = sp.getBoolean("name", "");
    

10、使用xml文件备份数据-使用StringBuffer拼接。


    我们一般备份短信都是用的xml文件保存,备份数据通常都是备份至sd卡中
    
    可以用StringBuffer拼接字符串,但是容易出错,而且如果字符串里面本来就包含了  <body> 等标签数据,解析的时候就会出现问题。
        a、创建用于存数据的类sms.java
        public class Sms {


            private String body;
            private long date;
            private int type;
            private String address;
            public Sms(String body, long date, int type, String address) {
                super();
                this.body = body;
                this.date = date;
                this.type = type;
                this.address = address;
            }
            public String getBody() {
                return body;
            }
            public void setBody(String body) {
                this.body = body;
            }
            public long getDate() {
                return date;
            }
            public void setDate(long date) {
                this.date = date;
            }
            public int getType() {
                return type;
            }
            public void setType(int type) {
                this.type = type;
            }
            public String getAddress() {
                return address;
            }
            public void setAddress(String address) {
                this.address = address;
            }
            
        }
        
        b、生成数据:
            smsList = new ArrayList<Sms>();用ArrayList保存
            for (int i = 0; i < 10; i++) {
                Sms sms = new Sms("hello" + i, System.currentTimeMillis(), 1, "12345678900");
                smsList.add(sms);
            }
            
        c、将数据写到xml文件中
        StringBuffer sb = new StringBuffer();
            sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");//添加头
            sb.append("<smss>");//添加根节点
            
            for (Sms sms : smsList) {//添加每条短信的标签
                sb.append("<sms>");
                
                sb.append("<body>");
                sb.append(sms.getBody()+"<body>");
                sb.append("</body>");
                
                sb.append("<date>");
                sb.append(sms.getDate());
                sb.append("</date>");
                
                sb.append("<type>");
                sb.append(sms.getType());
                sb.append("</type>");
                
                sb.append("<address>");
                sb.append(sms.getAddress());
                sb.append("</address>");
                
                sb.append("</sms>");
            }
            
            sb.append("</smss>");
            
            File file = new File("sdcard/sms.xml");
            try {
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(sb.toString().getBytes());
            } catch (Exception e) {
                 TODO Auto-generated catch block
                e.printStackTrace();
            }
        d、这样就完成了。


    
11、使用XMl序列化器生成xml文件
        //获取xml序列化器
XmlSerializer xs = Xml.newSerializer();
File file = new File("sdcard/sms2.xml");
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
//初始化
//xml文件中什么编码生成
xs.setOutput(fos, "utf-8");
//开始生成xml文件
//生成头结点
xs.startDocument("utf-8", true);//这个编码是xml文件头的utf-8编码

//生成开始标签
xs.startTag(null, "smss");

for (Sms sms : smsList) {
xs.startTag(null, "sms");

xs.startTag(null, "body");
xs.text(sms.getBody() + "<body>");
xs.endTag(null, "body");

xs.startTag(null, "type");
xs.text(sms.getType() + "");
xs.endTag(null, "type");

xs.startTag(null, "date");
xs.text(sms.getDate() + "");
xs.endTag(null, "date");

xs.startTag(null, "address");
xs.text(sms.getAddress());
xs.endTag(null, "address");

xs.endTag(null, "sms");
}

//生成结束标签
xs.endTag(null, "smss");

//告知序列化器生成xml结束
xs.endDocument();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


        
12、xml文件存好了,现在需要进行解析
        一般都是解析网络中获取的xml,发一个http请求,传回来xml数据
        
        a、获取src文件夹下的文件
            InputStream is = getClassLoader().getResourceAsStream("weather.xml");
        
        b、获取xmlpull解析器,XmlPullParser是一个接口不能new的
            XmlPullParser xp = Xml.newPullParser();
            
        c、初始化
xp.setInput(is, "gbk");//我们一般使用utf-8编码,当时我们window是用gbk的,如果用utf-8会出现乱码
            
        d、是以事件类型作为驱动解析的,读取一行解析一行
            //获取当前节点的事件类型
int type = xp.getEventType();
        e、处理流程
            City city = null;//City是一个用于存储数据的类
while(type != XmlPullParser.END_DOCUMENT){
switch (type) {
case XmlPullParser.START_TAG:
//获取当前节点的名字
if("weather".equals(xp.getName())){
cityList = new ArrayList<City>();//读到根节点,就创建一个ArrayList<City>,用于存储多个城市的天气信息
}
else if("city".equals(xp.getName())){
city = new City();//读到city这个标签,就创建一个City对象,用于当前城市的天气信息
}
else if("name".equals(xp.getName())){
//获取下一个节点的文本
String name = xp.nextText();
city.setName(name);
}
else if("temp".equals(xp.getName())){
//获取下一个节点的文本,把指针移动至当前节点的结束节点
String temp = xp.nextText();
city.setTemp(temp);
}
else if("pm25".equals(xp.getName())){
//获取下一个节点的文本
String pm25 = xp.nextText();
city.setPm25(pm25);
}
break;
case XmlPullParser.END_TAG:
if("city".equals(xp.getName())){
cityList.add(city);
}
break;


}
//把指针移动至下一个节点,并返回该节点的事件类型
type = xp.next();
}
               


    
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值