------- android培训、java培训、期待与您交流! ----------
File类概述和构造方法:
文件和目录路径名的抽象表示形式
1.构造方法:
Public File(String pathname):根据一个路径得到File对象;
Public File(Sting parenet , String child):根据一个目录和一个子文件/目录得到File对象
Public File ( File parent ,String child):根据一个父File对象和一个子文件/目录得到File对象
2.创建功能:
Public Boolean createNewFiel( ) : 创建文件 如果存在这样的文件,就不创建了
Public Boolean mkdir():创建文件夹如果存在这样的文件夹,就不创建了
Public Boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮那你创建出来。
3.删除功能:
Public Boolean deleta():
4.重命名功能:
Public Boolean renameTo(File dest)
如果路径名相同,就是改名;
如果路径名不同,就是改名并剪切;
路径以盘符开始;绝对路径 C:\\a.txt
路径不以盘符开始:相对路径 a.txt
5.判断功能:
Public Boolean isDirectory(): 判断是否是目录
Public Boolean isFile() :判断是否是文件
Public Boolean exists() :判断是否存在
Public Boolean canRead :判断是否可读
Public Boolean canWrite() : 判断是否可写
Public Boolean isHidden () : 判断是否隐藏
6.获取功能:
Public String getAbsolutepath():获取绝对路劲
Public String getPath():获取相对路径
Public String getName() : 获取名称
Public long length():获取长度
Public long lastModified(): 获取最后一次的修改时间,毫秒值;
把毫秒值转换成日期形式:
long lat=file3.lastModified();
System.out.println(lat);
Date d = new Date(lat);
SimpleDateFormat sdf = newSimpleDateFormat("yyy-MM-dd HH:mm:ss");
String s1= sdf.format(d);
System.out.println(s1);
7.获取的高级功能:
PublicString[] list() ::获取所有指定目录下的所有文件或者文件夹的名称数组
PublicFile[] listFiles():获取所有指定目录下的所有文件或者文件夹的File数组;
public static void main(String[] args) {
//指定一个目录
File file = new File("d:\\");
String[] strArray= file.list();
// System.out.println(strArray);
// for(String s :strArray){
// System.out.println(s);
File[] fileArray = file.listFiles();
for(File f: fileArray){
System.out.println(f);
System.out.println(f.getName());
}
}
案例:
判断D盘目录下是否有后缀名为.jpg的文件,如果有,将就输出此文件名称
//封装e判断目录
File file = new File("D:\\");
//获取该目录下所有文件或者文件夹的File数组
File[] fileArray = file.listFiles();
//遍历File数组,得到每一个File对象,然后判断;
for(File f: fileArray){
//System.out.println(f.getName());
//是否是文件
if(f.isFile()){
//继续判断是否以.jpg结尾
if(f.getName().endsWith(".jpg")){;
System.out.println(f.getName());
}
}
}
以上题目的另一种思路:
//封装D
Filefile= new File("D:\\");
//获取该目录下所有文件或者文件夹的String的数组
String[] strArray = file.list(new FilenameFilter(){
@Override
public boolean accept(File arg0, String arg1) {
//通过这个测试,我么知道了,到底把这个文件或者文件夹的名称加不加到数组中,取决于这里的返回值是true还是false;
//所以,这个的ture或者false应该是我们通过某种判断得到的
System.out.println(arg0 + "---"+ arg1 );
File file = new File(arg0 ,arg1);
System.out.println(file);
boolean flag = file.isFile();
boolean flag2 = arg1.endsWith(".jpg");
//return flag&& flag2;
return new File(arg0 ,arg1).isFile() && file.getName().endsWith("jpg");
}
});
//遍历
for(String s :strArray){
System.out.println("---");
System.out.println(s);
}
}
}
递归概述
方法定义中调用方法本身的现象;
方法的嵌套调用,这不是递归。
Math.max(Math,max(a,b) ,c)
Public void show(){
Show()(
}
注意事项:
A:递归一定要有出口
B:递归的次数不能太多,否则就内存溢出
C:构造方法不能递归使用;
public class DiGuiDemo {
public static void main(String[] args) {
int jc = 1;
for(int x=2; x<=5;x++){
jc*=x;
}
System.out.println("5的阶乘:"+jc);
//递归:
}
public static int jiecheng(int n){
if(n==1){
return 1;
}else{
return n*jiecheng(n-1);
}
}
}
递归不死兔子问题:
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
int[] arr= new int[20];
arr[0]=1;
arr[1]=1;
for(int x=2;x<arr.length;x++){
arr[x]=arr[x-1]+arr[x-2];
}
System.out.println(arr[19]);
System.out.println("-------");
int a=1;
int b=1;
for(int x=0; x<18;x++){
//临时变量存储上一次的a;
int temp=a;
a=b;
b=temp+b;
}
System.out.println(b);
System.out.println("---------");
System.out.println(ilb(20));
}
public static int ilb(int n){
if(n==1 || n==2){
return 1;
}else{
return ilb(n-1) + ilb(n-2);
}
}
}
递归遍历目录下指定后缀名结尾的文件名称
/*
* 需求:把D:\目录下所有的java结尾的文件的绝对路径输出在控制台;
* 分析:
* A:封装目录
* B:获取该目录下所有的文件或者文件夹的File数组
* C:遍历该File数组,得到每一个File对象;
* D:判断该File对象是否是文件夹
* 是:回到B
* 否:继续判断是否以.java结尾
* 是:就输出该文件的绝对路径
* 否:不搭理它;
*
*/
public class FilePathDemo {
public static void main(String[] args) {
//封装目录
File srcFolder = new File("D:\\");
//递归功能实现
getAllFilePaths(srcFolder);
}
private static void getAllFilePaths(File srcFolder) {
// TODOAuto-generated method stub
//获取该目录下所有的文件或者文件夹的File数组
File[] fileArray = srcFolder.listFiles();
//遍历该File数组,得到每一个File对象
for(File file : fileArray){
if(file.isDirectory()){
getAllFilePaths(file);
}else{
//继续判断是否以.java结尾
if(file.getName().endsWith(".java")){
//就输出该文件件的绝对路径;
System.out.println(file.getAbsolutePath());
}
}
}
}
}
递归删除带内容的目录:
*
* 需求:递归删除带内容的目录
* 目录:aaa
* 分析:
* A:封装目录
* B:获取该目录下的所有文件或者文件夹的File数组
* C:边路该File数组,得到每一个File对象
* D:判断该File对象是否是文件夹
* 是:回到B
* 否:就删除
*
*/
public class delete {
public static void main(String[] args) {
//封装目录
FilesrcFile = new File("aaa");
//递归实现
deleteFolder(srcFile);
}
private static void deleteFolder(File srcFile) {
// TODOAuto-generated method stub
//获取该目录下的所有文件或者文件夹的File数组
File[] fileArray = srcFile.listFiles();
//遍历每一个获取数组的对象
if(fileArray != null){
for(File fs : fileArray){
System.out.println(fs);
if(fs.isDirectory()){
deleteFolder(fs);
}else{
System.out.println( fs.getAbsoluteFile()+"---"+fs.getName()+"----"+fs.delete());
}
}
System.out.println(srcFile.getName()+"------"+srcFile.delete());
}
}
}
IO流概述:
IO流用来处理设备之间的数据传输
上传文件和下载文件:
Java对数据的操作是通过流的方式;
Java用于操作流的对象都在IO包中;
1. 按照数据流向:
输入流 读入数据
输出流 写入数据
2. 按照数据类型:
字节流
字节输入流 读取数据 inputStream
字节输出流 写出数据 outputStream
字符流
输入流 读取数据 Reader
输出流 写出数据 Writer
什么情况下使用哪种流呢?
如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。
如果什么都不知道的,就用字节流;
注意:一般我们探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。
IO流常用基类:
1.字节流的抽象基类;
inputStream OutputStream
2.字符流的抽象基类:
Reader Writer
注意:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:inputStream的子类FileInputStream。
如:Reader的子类FileReader.
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
/*
* 创建字节输出流对象做了几件事:
* A:调用系统功能区创建文件
* B:创建fos对象
* C:把fos对象指向这个文件
*
*/
//写入数据
fos.write("hello,ios".getBytes());
//释放资源
//关闭此文件输出流并释放与此流有关的所有系统资源;
fos.close();
为什么一定要close();
A:让流对象编程垃圾,这样就可以被垃圾回收器回收了。
B:通知系统去释放跟该文件相关的资源;
字节流写入数据的方式:
Public void write(int b): 写一个字节
Public void write(byte[] b):写一个字节数组
Public void write(byte[] b ,int off, intlen):写一个字节数组的一部分
//创建字节流输出对象
OutputStream os= newFileOutputStream("fos2.txt"); //多态
FileOutputStream fos = new FileOutputStream("fos.txt");
//调用write方法;
fos.write(97);// 97 --底层二进制数据---通过记事本打开---找97对应的字符值--a
fos.write(57);//字符9
fos.write(55);//字符7
//public void write(byte[] b ):写一个字节数组
byte[] bys= {97,98,99,100,101}; //byte[] bys = {a, b, c, d, e };
fos.write(bys);
fos.write(bys,1,3);
fos.close();
字节流写数据常见问题:
1.创建字节输出流到底做了哪些事情?
A:调用系统功能区创建文件
B:创建fos对象
C:把fos对象指向这个文件
2.数据写成功后,为什么要close()?
A:让流对象编程垃圾,这样就可以被垃圾回收器回收了。
B:通知系统去释放跟该文件相关的资源
3. 如何实现数据的换行?
写入换行数据;
Linux:\n
Windows: \r\n
Mac:\r
4. 如何实现数据的追加写入?
用构造方法带得第二个参数是true的情况即可;
字节流写数据加入异常处理:
// //分开做异常处理;
// FileOutputStream fos=null;
// try {
// fos = newFileOutputStream("fos4.txt");
// } catch (FileNotFoundException e1) {
// // TODO Auto-generated catch block
// e1.printStackTrace();
// }
// try {
// fos.write("helle 八月".getBytes());
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// try {
// fos.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//一起做异常
// try{
// FileOutputStream fos = new FileOutputStream("fos5.txt");
// fos.write("java".getBytes());
// fos.close();
// }catch(FileNotFoundException e){
// e.printStackTrace();
// }catch(IOException e){
// e.printStackTrace();
// }
//改进版
//为了在finally里面能够看到该对象就必须定义到外面,为了访问不出问题,还必须给初始化值;
FileOutputStream fos=null;
try{
fos= new FileOutputStream("fos5.txt");
fos.write("java".getBytes());
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
//如果fos不是null,才需要close();
//为了保证close()一定执行,就放到这里了;
if(fos != null)
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
FileinputStream读取数据:
读取数据的方式:
A:int read(); 一次读取一个字节
B:int read(byte[] b):一次读取一个字节数组;
int by=0;
while((by =fis.read()) !=-1){
System.out.println((char)by);
}
字节流复制文案例:
/*
* 复制文本文件。
*
* 数据源:从哪里来
* a.txt -- 读取数据 -- FileInputStream
*
* 目的地:到哪里去
* b.txt -- 写数据 -- FileOutputStream
*
*java.io.FileNotFoundException: a.txt (系统找不到指定的文件。)
*
* 这一次复制中文没有出现任何问题,为什么呢?
* 上一次我们出现问题的原因在于我们每次获取到一个字节数据,就把该字节数据转换为了字符数据,然后输出到控制台。
* 而这一次呢?确实通过IO流读取数据,写到文本文件,你读取一个字节,我就写入一个字节,你没有做任何的转换。
* 它会自己做转换。
*/
public class CopyFileDemo {
publicstatic void main(String[] args) throws IOException {
// 封装数据源
FileInputStreamfis = new FileInputStream("a.txt");
// 封装目的地
FileOutputStreamfos = new FileOutputStream("b.txt");
int by = 0;
while ((by = fis.read()) !=-1) {
fos.write(by);
}
// 释放资源(先关谁都行)
fos.close();
fis.close();
}
}
复制图片:
// 封装数据源
FileInputStream fis = new FileInputStream("e:mm.jpg");
// 封装目的地
FileOutputStream fos = new FileOutputStream("mn.jpg");
// 复制数据
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源
fos.close();
fis.close();
}
复制歌曲:
// 封装数据源
FileInputStream fis = new FileInputStream("喜欢你.mp4");
// 封装目的地
FileOutputStream fos = new FileOutputStream("copy.mp4");
// 复制数据
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源
fos.close();
fis.close();
}
}
FileInputStream读取数据一次一个字节数组:
int read(byte[] b):一次读取一个字节数组;
读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1;
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
FileInputStream读取数据的两种方式比较图解:
用字节数组读取数据案例:
1.复制文本案例:
// 封装数据源
FileInputStream fis = new FileInputStream("c:\\a.txt");
FileOutputStream fos = new FileOutputStream("d:\\b.txt");
// 复制数据
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 释放资源
fos.close();
fis.close();
}
2.复制MP3:
// 封装数据源
FileInputStream fis = new FileInputStream("e:\\喜欢你.mp3");
// 封装目的地
FileOutputStream fos = new FileOutputStream("copy.mp3");
// 复制数据
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 释放资源
fos.close();
fis.close();
}
}
字节缓冲流:
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流;
字节缓冲输出流:
BufferedOutputStream
构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了;
BufferedOutputStream
(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流
为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
原因很简单,字节缓冲区流仅仅提供缓冲区,为高效设计的。但是呢,真正的读写操作还得靠基本的流对象实现。
//BufferedOutputStream(OutputStream out)
// FileOutputStream fos = newFileOutputStream("bos.txt");
// BufferedOutputStream bos = newBufferedOutputStream(fos);
// 简单写法
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));
// 写数据
bos.write("hello".getBytes());
// 释放资源
bos.close();
}
字节缓冲输入流:
BufferedInputStream
BufferedInputStream bus = new BufferedInputStream(new FileInputStream("a.txt"));
// bus.read();
//读取数据;
// int by = 0;
// while((by= bus.read())!= -1){
// System.out.print((char)by);
// }
System.out.println("----------");
byte[] bys = new byte[1024];
int len = 0;
while((len = bus.read(bys)) != -1){
System.out.println(new String(bys ,0 ,len));
}
//释放资源
bus.close();
}
转换流出现的原因及思想:
由于字节流操作中文不是特别方便,所以,java提供了转换流;
字符流 = 字节流 + 编码表.
编码表:
String(byte[ ] bytes, String charsetName):通过指定的字符集解码字节数组
Byte[] getByetes(String charsetName):使用指定的字符集集合把字符串编码为字节数组;
编码:把看得懂得看成看不懂的
String -- byte[]
解码: 把看不懂的变成看得懂的
String s = "你好";
// String -- byte[]
byte[] bys = s.getBytes(); //[-60, -29, -70, -61]
// byte[] bys =s.getBytes("GBK");// [-60, -29, -70, -61]
// byte[] bys =s.getBytes("UTF-8");// [-28, -67, -96, -27, -91, -67]
System.out.println(Arrays.toString(bys));
// byte[] -- String
String ss = new String(bys);// 你好
// String ss = new String(bys,"GBK"); // 你好
// String ss = new String(bys,"UTF-8"); // ???
System.out.println(ss);
Byte [] –String
// 创建字节输入流对象
FileInputStream fis = newFileInputStream("a.txt");
// 读取数据
// int by = 0;
// while ((by = fis.read()) !=-1) {
// System.out.print((char)by);
// }
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys))!= -1) {
System.out.print(newString(bys, 0, len));
}
// 释放资源
fis.close();
IO流转换流:
OutputStreamWriter(OutputStream out ) :根据默认编码把字节流的数据转换为字符流
OutputStreamWriter(OutputStream out, StringcharsetName):根据指定编码把字节流数据转换为字符流
// 创建对象
// OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream(
// "osw.txt")); // 默认GBK
// OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream(
// "osw.txt"),"GBK"); // 指定GBK
OutputStreamWriter osw = newOutputStreamWriter(new FileOutputStream(
"osw.txt"),"UTF-8"); // 指定UTF-8
// 写数据
osw.write("中国");
// 释放资源
osw.close();
}
InputStreamReader(InputStream in):默认的编码读取数据额;
InputStreamReader(InputStream in ,StringcharsetName):用指定的编码读取数据;
// 创建对象
//InputStreamReader isr = new InputStreamReader(new FileInputStream(
//"osw.txt"));
//InputStreamReader isr = new InputStreamReader(new FileInputStream(
//"osw.txt"), "GBK");
InputStreamReader isr = newInputStreamReader(new FileInputStream(
"osw.txt"),"UTF-8");
// 读取数据
// 一次读取一个字符
int ch = 0;
while ((ch = isr.read()) !=-1) {
System.out.print((char)ch);
}
// 释放资源
isr.close();
}
字符流读写数据:
字符流的5种写数据的方式:
Public void write(int c): 写一个字符;
Public void Write( char[] cbuf):写一个字符数组;
Public void write(char[] cbuf, int off, int len):写一个字符数组的一bufen
Public void write(String str):写一个字符串
Public void write(String str ,int off,int len):写一个字符串的一部分;
字符流操作要注意的问题:
flush()的作用:刷新流
flush()和close()的区别:
flush():仅仅刷新缓冲区,刷新之后,流对象还以继续使用。
close():关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
//创建对象;
OutputStreamWriter outw = new OutputStreamWriter(new FileOutputStream("a.txt"));
//写数据:
outw.write(97);
outw.write("97");
outw.flush();
char[] chs= {'a', 'b', 'c' ,'d'};
outw.write(chs);
outw.flush();
outw.write("我喜欢你");
outw.flush();
outw.close();
}
InputStreamReader的两种读数据的方式:
Int read(): 一次读取一个字符;
Int read(char[] chs):一次读取一个字符数组;
// 创建对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"StringDemo.java"));
// 一次读取一个字符
// int ch = 0;
// while ((ch = isr.read()) != -1) {
// System.out.print((char) ch);
// }
// 一次读取一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
isr.close();
}
字符流复制文本文件:
把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt
InputStreamReaderisr = new InputStreamReader(new FileInputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//读写数据额
// int ch=0;
// while((ch=isr.read())!= -1){
// osw.write(ch);
// }
char[] bys= new char[1024];
int len=0;
System.out.println(bys);
// System.out.println(isr.read(bys));
while((len=isr.read(bys))!=-1){
osw.write(bys, 0, len);
osw.flush();
}
//释放资源
osw.close();
isr.close();
}
转换流的简化写法:
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以为了简化我们的书写,转换流提供了相应的子类;
FileWriter
FileReader
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
// int ch= 0;
// while((ch=fr.read())!= -1){
// fw.write(ch);
// }
//一次一个字符数组;;
char[] cha = new char[1024];
int len =0;
while((len= fr.read(cha))!=-1){
fw.write(cha, 0, len);
}
fw.close();
fw.close();
}
字符缓冲输出流:
字符流为了高效读写,也提供了对应的字符缓冲流:
BufferedWriter: 字符缓冲输出流;
将文本写入字符输出流,缓冲各个字符,从提供单个字符,数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
BufferedReader:字符缓冲输入流:
从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取。
可以指定缓冲区大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
1. 字符缓冲流复制文本文件;
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 两种方式其中的一种一次读写一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
bw.flush();
}
// 释放资源
bw.close();
br.close();
字符缓冲流的特殊方法:
BufferedWriter:
Public void newLine():根据系统来决定换行符
BufferedReader:
Public String readLine():一次读取一行数据;
包含该行内容的字符串,不包含任何行终止符,如果已达到流末尾,则返回null;
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
// public String readLine():一次读取一行数据
// String line = br.readLine();
// System.out.println(line);
// line = br.readLine();
// System.out.println(line);
// 最终版代码
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
}
private static void write() throws IOException {
// 创建字符缓冲输出流对象
BufferedWriterbw = new BufferedWriter(new FileWriter("bw2.txt"));
for (int x = 0; x < 10; x++) {
bw.write("hello" + x);
// bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
}
IO流小结图解: