关闭

黑马程序员---IO流一

615人阅读 评论(0) 收藏 举报
分类:

IO流一

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1.File类

1.1 概述

1.1.1 File类出现的必要性

存储在变量、数组和对象中的数据是暂时的,当程序终止他们时就会丢失,为了能够永久地保存程序中创建的数据,需要将他们存储到硬盘或光盘的文件,这些文件可以移动,传送,亦可以被其他程序使用。由于数据存储在文件中,所以我们要掌握它,就需要学习一种与文件密切相关的类,叫做File类。

定义

File类描述的是一个文件或文件夹(也可叫目录)。

1.1.2构造一个File类的实例(File的构造函数)

注:

1)File 对象没有无参构造方法,创建对象需要传参。

2)创建File对象需要导包,import java.io.File

3)File类的对象,既可以代表文件也可以代表文件夹。

1.2 路径

   路径就是文件或文件夹所在的位置

1.2.1 路径分割符

 上下级文件夹之间使用分隔符分开。

 在windows中分隔符为‘\’,在Unix/Linux中分隔符为‘/’

专业的做法是File.separatorChar – 这个值会根据系统得到相应的分割符。

 如 new File(“C:”+File.separatorChar+ “file.txt’);

1.2.2 绝对路径与相对路径

对于UNIX平台,绝对路径名的前缀是“/”。相对路径名没有前缀。

绝对路径

对于Windows平台,绝对路径的前缀由驱动器号和一个“:”组成,例:“c:\\...”。相对路径没有盘符前缀

相对路径

    相对路径是指相对于某位置的路径,是指相对于当前目录。在执行Java程序时,相对路径为执行javav命令时当前所在的目录。

注:一般在使用时,建议使用绝对路径,相对路径容易出问题

1.3 File类的常用方法


代码实例: 

1)列出指定目录下的所有子文件名与所有子目录名

package com.ping.File;
import java.io.File;
public class FileDemo1 {
     /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
//指定目录还有系统指定的分隔符
        listAllFilesAndDir("E:"+File.separatorChar + "Java基础资料");  
    }
//将方法封装
    public static void listAllFilesAndDir(String path){ 
        File dir = new File(path);
//将指定文件夹里的文件封装成一个文件数组
        File [] names = dir.listFiles();             
        System.out.println("该目录里有:");
//循环输出文件名
        for(int i = 0 ; i < names.length ; i ++){   
            File file = names[i];
            System.out.println(file.getName());
        }
    }
}
输出
该目录里有:
java毕向东java基础
学通Java的24堂课
学通Java的24堂课_120集大型多媒体教学视频.iso
魔乐科技

2)列出指定目录中所有的子文件名与所有的子目录名,目录与文件分开输出

package com.ping.File;
import java.io.File;
public class FileDemo1 {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
//指定目录还有系统指定的分隔符
        listAllFilesAndDir("E:"+File.separatorChar + "Java基础资料");  
    }
//将方法封装
    public static void listAllFilesAndDir(String path){ 
        File dir = new File(path);
//将指定文件夹里的文件封装成一个文件数组
        File [] names = dir.listFiles();             
        System.out.println("该目录里有:");
        System.out.println("文件");
//循环输出文件夹中的文件
        for(int i = 0 ; i < names.length ; i ++){   
            File file = names[i];
//判断是否是文件
            if(file.isFile()){                     
                System.out.print( file.getName());
            }
        }
        System.out.println("\n文件夹");
//循环输出文件夹中的子文件夹
        for(int i = 0 ; i < names.length ; i ++){
            File files = names[i];
//判断是否是文件夹
            if(files.isDirectory()){          
                System.out.println(files.getName() );
            }
        }
    }
}
输出:
该目录里有:
文件
学通Java的24堂课_120集大型多媒体教学视频.iso
文件夹
java毕向东java基础
学通Java的24堂课
魔乐科技
3)列出目录中所有扩展名为.java的文件
package com.ping.File;
import java.io.File;
public class FileDemo2 {
    public static void main(String [] args){
        String path = "H:" + File.separatorChar + "day13";
        File file = new File(path);
        listFiles(file,"java");
    }
    public static void listFiles(File dir , String extension){
//将目录文件放到一个数组中
        File [] files = dir.listFiles(); 
//输出目录               
        for(int i = 0 ; i < files.length; i ++ ) {  
            File file = files[i];
//满足条件即输出
            if(file.getName().endsWith(extension)){  
                System.out.println(file.getName());
            }
        }
    }
}
输出:
CollectionDemo.java
CollectionDemo_2.java
CollectionDemo_3.java
CollectionDemo_4.java

4)用FilenameFIlter接口写一个工具类,这样就可以过滤各种后缀的文件

package com.ping.File;
import java.io.File;
import java.io.FilenameFilter;
public class FileDemo3 {
    /**
     * @param args
     */
public static void main(String[] args) {
        // TODO Auto-generated method stub
//目录
        String path = "D:"+File.separatorChar;
//创建File文件       
        File file = new File(path);
//把条件的放到方法中                
        listFiles(file,"doc");                      
    }
    public static void listFiles(File dir , String name){
//将符合要求的放在文件数组里
        String [] files = dir.list(new DirFilter(name));   
        for(int i = 0 ; i < files.length ; i ++){
//输出        
            System.out.println(files[i]);
        }
    }
}
//过滤器,将筛选出符合要求的
class DirFilter implements FilenameFilter{   
    private String extention;
    public DirFilter(String extention) {
        super();
        this.extention = extention;
    }
    public DirFilter() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public boolean accept(File dir, String name) {
        // TODO Auto-generated method stub
        return name.endsWith(extention);
    }
}
输出:
CSS.doc
exam.doc
html和CSS笔记.doc
JavaScript.doc
java_IO操作_(读写、追加、删除、移动、复制、修改).doc
JAVA正则表达式语法.doc
Java线程及多线程技术及应用.doc
Java网络socket编程详解.doc
Java网络编程精解——孙卫琴.doc

2.IO流

 File类只是操作文件,文件的内容如何处理就需要使用io流技术。

2.1 IO流简介(Input/Output)

  Java对设备中数据的操作是通过流的方式。

  表示任何有能力产出数据的数据源对象,或者是有能力接受数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。I/O流用来处理设备之间的数据传输。设备是指硬盘、内存、键盘录入等。

 Java用来操作流的对象都在IO包中。IO流技术主要用来处理设备之间的数据传输。

 流按操作数据类型的不同分为两种:字节流和字符流

 流按流向分为:输入流,输出流

2.2 字节流

计算机中都是二进制数据,一个字节是8个二进制位。字节可以表示所有数据,比如文本,音频,视频,图片,都是作为字节存在的。

二进制文件的优势在于它的处理效率比文本文件高。

因为File对象封装的是文件或者路径属性,但不包含文件的读写数据的方法。为了实现对文件的读和写,需要用不用Java的IO创建对象。

字节流的抽象基类。

输入流:java.io.InputStream

输出流:java.io.OutputStream

特点:

字节流的抽象基类派生出来的子类名称都是以其父类名作为子类的后缀。如FileInputStream,ByteArrayInputStream

说明:

字节流处理的单元是一个字节,用于操作二进制(所有计算机文件都是二进制。)

2.2.1 字节输入流(InputStream)

---|java.lang.Object
   ---|java.io.InputStream

主要方法:

read()方法:从输入流中读取数据的下一个字节。返回0~255范围内的int字节值。如果已经到达流的末尾没有可用的字节,则返回 -1 ;

int read(byte[]b):从输入流中读入一定长度的字节,并以整数的形式返回字节数。

因为InputStream是抽象数,所以我们要用到它的子类FileInputStream类

实现:显示指定文件内容的步骤

1)明确使用什么流:使用输入流---FileInputStream

2)打开流(创建流)

3)通过流读取内容

4)关闭流

2.2.2 FileInputStream

创建FileInputStream实例


1)使用read()方式读取数据代码实例:

package com.ping.IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 //指定文件的路径
        String path = "C:"+ File.separatorChar + "a.txt"; 
        showContent(path);
    }
    private static void showContent(String path){
//防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;                  
        try {
//创建FileInputStream对象
             fis = new FileInputStream(path);
//用len来接收读取的字节     
            int len ; 
//循环读取,到句末为止               
            while((len = fis.read()) != -1){                     
                System.out.print((char)len);
                len = fis.read();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            try {
//关闭流
                fis.close();                   
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
输出:
dfeeeeeeeeeesdfedsferfere

2)使用read(byte[]b)方法,使用缓冲区

使用read方法的时间,流需要读一次处理一次,可以将读到的数据装入到字节数组中,一次性的操作数组,可以提高效率。

 public static void showContent2(String path) {
// 防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;
        try {
// 创建FileInputStream对象
            fis = new FileInputStream(path);
//使用缓冲区来接收数据
            byte[] by = new byte[1024];
//读取数组的长度      
            int len = fis.read(by);         
            for (int i = 0; i < len; i++) {
//将byte强转为char
                System.out.print((char) by[i]);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
//关闭流
                fis.close();                        
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
3)使用read(byte[]by , int start , int len)读取数据

Start ----开始的位置

Len ---希望读取的长度

简单来说就是,从什么地方开始装多少数据

   public static void showContent3(String path) {
 // 防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;
        try {
// 创建FileInputStream对象
            fis = new FileInputStream(path);
//使用缓冲区来接收数据
            byte[] by = new byte[1024];      
            int start = 3 ;
            int length = 4;
//读取数组的长度
            int len = fis.read(by , start , length);         
            for (int i = 0; i < len; i++) {
//将byte强转为char
                System.out.print((char) by[i]);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
//关闭流
                fis.close();                        
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
4)使用skip()方法—跳过文件的一部分
public static void showContent2(String path) {
// 防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;
        try {
// 创建FileInputStream对象
            fis = new FileInputStr eam(path);
//使用缓冲区来接收数据
            byte[] by = new byte[1024];
//跳过前边的8个字节      
            fis.skip(8);
//读取数组的长度                      
            int len = fis.read(by);         
            for (int i = 0; i < len; i++) {
//将byte强转为char
                System.out.print((char) by[i]);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
//关闭流
                fis.close();                        
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
输出:
//加入skip前
Dfeeeeeeeeeesdfedsferfere
//后
eeeesdfedsferfere

5)使用缓冲,读完所有内容

public static void showContent4(String path) {
// 防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;
        try {
// 创建FileInputStream对象
            fis = new FileInputStream(path);
//使用缓冲区来接收数据
            byte[] by = new byte[1024];      
            int len = fis.read(by);
            System.out.println(len);
//将字符数组放进字符串中
            String buffer = new String(by,0,len);
            System.out.println(buffer);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
//关闭流
                fis.close();                        
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
输出:
25
dfeeeeeeeeeesdfedsferfere
6)例5中,若字符数组的内容超1024的话,数组就存不下了,最好的方法就是循环读取

public static void showContent4(String path) {
// 防止发生异常,在捕获异常前声明FileInputStrem
        FileInputStream fis = null;
        try {
// 创建FileInputStream对象
            fis = new FileInputStream(path);
//使用缓冲区来接收数据
            byte[] by = new byte[1024];       
            int len = fis.read(by);
            while((len = fis.read(by)) != -1){
//循环读取数据
                System.out.println(new String(by , 0 , len));
            }
            //String buffer = new String(by,0,len);
          //  System.out.println(buffer);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
//关闭流
                fis.close();                        
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
使用些方法,可以读取大数据文档

2.2.3 OutputStream(字节输出流)

需要向指定文件写入数据,需要用到输出流。

该类是抽象类,需要使用具体的实现类来创建对象写入文件,OutputStream的实现类是FileOutputStream,通过FileInputStream创建流对象,必须指定数据要存放的目的地。通过构造函数指定数据要存入的目的地,在指定位置建立了数据存放的目的文件。

常用的构造方法有


主要方法


代码练习

1)把“HelloWorld”写到“c:/a.txt”的文件中

public static void writeFile(String path){
        FileOutputStream fos  = null;
            try {
                fos = new FileOutputStream(path);
                fos.write('H');
                fos.write('e');
                fos.write('l');
                fos.write('l');
                fos.write('o');
                fos.write(' ');
                fos.write('W');
                fos.write('o');
                fos.write('r');
                fos.write('l');
                fos.write('d');
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
注:使用此方法发现虽然内容是写进去了,但是原来的内容却不见,没有达到追加的效果,怎样让文件中追加内容呢?
FileOutputStream中有一个构造方法FileOutputStream(File file , Boolean append)的第二个参数,append就是是否追加的意思,若true,则追加。False则覆盖。

2)追加操作

 public static void writeFile(String path){
        FileOutputStream fos  = null;
            try {
                fos = new FileOutputStream(path,true);
                fos.write('H');
                fos.write('e');
                fos.write('l');
                fos.write('l');
                fos.write('o');
                fos.write(' ');
                fos.write('W');
                fos.write('o');
                fos.write('r');
                fos.write('l');
                fos.write('d');
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
可以看到,内容是追加上的,在原来HelloWorld的后面再加上HelloWorld

3)用字符数组输入数据

如上,发现如果文件是一个一个字节地输入的话,相当麻烦,我们可以使用字符数组来存储数组

package com.ping.IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String path = "c:" + File.separatorChar + "a.txt";
//要写入的内容
        String content = "Hello Java";
//调用方法                  
        writeFile(path,content);                      
        readFile(path);
    }
    public static void writeFile(String path,String content){
 //声明FileOutputStream
        FileOutputStream fos  = null;                
            try {//创建FileOutputStream对象
                fos = new FileOutputStream(path,true);
//将字符串转换成字符数组
                byte [] buffer = content.getBytes();
//将字符数组的内容写入到指定文件  
                fos.write(buffer);                   
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }//创建一个读文件的方法查找方法
    public static void readFile(String path){
//声明FileInputStream      
        FileInputStream fis = null;                    
        try {
//创建FileInputStream对象                                
            fis = new FileInputStream(path);                            
            int len;
 //缓冲区
            byte [] by = new byte[1024];               
            while((len = fis.read(by))!=-1){
                System.out.print(new String(by , 0 , len));
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
输出
Hello WorldHello WorldHello JavaHello JavaHello Java

4)实现文件拷贝

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFileDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String path = "D:" + File.separatorChar + "a.txt";
        String target = "C:" + File.separatorChar + "b.txt";
//若此文件不存在,则创建
        File file = new File(target);                     
        if(file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
//调用复制办法
        copyFile(path,target);
//读取文件                          
        readFile(target);                              
    }
//复制文件的方法
    public static void copyFile(String path , String content){
//声明输入输出流      
        FileInputStream fis = null;                                  
        FileOutputStream fos = null;
        try {
//创建了字节输入输出
            fis = new FileInputStream(path);                       
            fos = new FileOutputStream(content);
            byte [] by = new byte[1024];
            int len;
            while((len = fis.read(by)) != -1){
//输出流将输入流的数据写入指定文件
                fos.write(by , 0 , len);                
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }try {
            fis.close();
            fos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
//读取文件的方法
    public static void readFile(String path){  
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(path);
            byte [] by = new byte[1024];
            int len ;
            while((len = fis.read(by)) != -1){
                System.out.print(new String(by , 0 , len));
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }try {
            fis.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
输出:
Hello WorldHello WorldHello JavaHello JavaHello Java

2.3 字节缓冲流

上述代码我们为了提高流的使用效率,自定义了字节数组,作为缓冲区。其实Java本身就提供了专门的字节缓冲流来提高效率。

2.3.1 BufferedInputStream和BufferedOutputStream

BufferedInputStream和BufferedOutputStream类可以通过减少读写次数来提高输入和输出的速度。它们内部有一个缓冲区,用来提高处理效率。缓冲区的大小是可以设置的。它们内部也是封装了字节数组。若不指定缓冲区大小,默认的字节是8192.

缓冲区输入流与缓冲区输出流要配合使用。缓冲区输入流将读取出的数据读入缓冲区,当缓冲区满时,缓冲区输出流会将数据输出。

代码实例:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String path = "c:\\a.rmvb";
        String target = "c:\\b.rmvb";                       
        copyFile(path,target);
    }
//复制文件的方法
    public static void copyFile(String path , String target){
//将输入输出流与缓冲流都先声明  
        FileInputStream fis = null;                             
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
//将输入输出流与缓冲流创建
            fis = new FileInputStream(path);                   
            fos = new FileOutputStream(target);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            int len ;
//将文件复制到指定文件
            while((len = bis.read()) != -1){                  
                bos.write(len);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            bis.close();
            bos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.递归

3.1 概念

递归作为一种算法在程序设计语言中广泛应用。是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象。(自己调用自己,有结束条件)

注:递归时一定要明确结束条件。

数学中的递归---阶乘

定义:1—N(包括N)的所有的整数乘积就是3!。

3!= 3 * 2 * 1;

用程序计算阶乘

import java.util.Scanner;
public class FactorialDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        System.out.println("n * n-1 * ...... * 1(请输入n):");
        int i = input.nextInt();
        System.out.println("n * n-1 * ...... * 1 = " + factorial(i));
    }
//计算阶乘的方法
    public static long factorial(int i){
//当n = 1 是返回1;     
        if (i == 1){                           
            return 1;
        }else{
            return i*factorial(i -1);
        }
    }
}
输出:
n * n-1 * ...... * 1(请输入n):
20
n * n-1 * ...... * 1 = 2432902008176640000

代码练习:

1.      删除一个非空的目录。

import java.io.File;
public class DeleteDirectory {  /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //新建File对象
        File file = new File("E:" + File.separatorChar + "书籍");
        //调用方法
        deleteFile(file);
    }
//方法
    private static void deleteFile(File file) {
        //判断文件是否存在
        if(!file.exists()){
            System.out.println("路径不存在!");
            return;
        }
        //判断文件是否目录
        if(!file.isDirectory()){
            System.out.println("这并不是目录");
            return;
        }
        //将目录中的文件放在一个数组里
        File [] files = file.listFiles();
        //循环判断如果是文件则删除,如果是文件夹就重新调用方法
        for (int i = 0; i < files.length; i++) {
            if(files[i].isFile()){
                files[i].delete();
            }else if(files[i].isDirectory()){
                deleteFile(files[i]);
            }
        }
        //把文件夹本身也删除
        file.delete();
        if(!file.exists()){
            System.out.println("删除成功!");
        }
    }
}

2.      移动一个非空目录到另一个地方。

public class CutDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 源文件
        File src = new File("D:" + File.separatorChar + "书籍");
        // 目录文件夹
        File dest = new File("E:");
        // 调用方法
        cutFile(src, dest);
    }
    public static void cutFile(File srcDir, File dest) {
        // 判断数据源和目标源是否存在
        if (!srcDir.exists() || !dest.exists()) {
            System.out.println("数据源或目标源不存在!");
            return;
        }
        // 判断数据源和目标源是否是目录
        if (!srcDir.isDirectory() || !dest.isDirectory()) {
            System.out.println("数据源或目标源非目录");
            return;
        }
        // 得到源文件的文件名
        String srcDirName = srcDir.getName();
        // 新建目标源的文件
        File destDir = new File(dest + srcDirName);
        // 创建
        destDir.mkdir();
        // 读取数据源的里文件
        File[] listFiles = srcDir.listFiles();
        for (File f : listFiles) {
            // 文件则剪切
            if (f.isFile()) {
                f.renameTo(new File(destDir, f.getName()));
                // 目录则递归
            } else if (f.isDirectory()) {
                cutFile(f, new File(destDir, File.separator));
            }
        }
        srcDir.delete();
    }
}
 ----------- android培训java培训、java学习型技术博客期待与您交流! ------------
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:28025次
    • 积分:666
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:14篇
    • 译文:1篇
    • 评论:3条
    最新评论