一。File类:
File类可以表示文件或者文件夹
public File(String path);
public File(String parent,String child);
public File(File parent,String child);
public class FileDemo01 {
public static void main(String[] args) {
//1.构造方法1
File f1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
System.out.println(f1);
//2.构造方法2
File f2 = new File("C:\\Users\\Administrator","Desktop\\temp\\aaa");
System.out.println(f2);
//2.构造方法3
File parent = new File("C:\\Users\\Administrator");
File f3 = new File(parent,"Desktop\\temp\\aaa");
System.out.println(f3);
}
}
File类的获取方法
public String getAbsolutePath(); 获取该File对象的绝对路径
public String getPath(); 获取该File对象构造时,传入的路径
public String getName(); 获取该File对象的代表的文件或者文件夹的名字
public long length(); 获取该File对象的大小(单位为字节)
public class FileDemo02 {
public static void main(String[] args) {
//File类的获取方法
File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
//1.getAbsolutePath
String absolutePath = ff.getAbsolutePath();
System.out.println(absolutePath);
//2.getPath
String path = ff.getPath();
System.out.println(path);
//3.getName
String name = ff.getName();
System.out.println(name);
//4.length
long len = ff.length();
System.out.println(len+"字节");
}
}
注意:length方法只能获取文件的大小,不能获取文件夹的大小
相对路径和绝对路径
绝对路径: 是指以盘符开头的路径
比如: "C:\Users\Administrator\Desktop\temp\aaa\1.txt"
相对路径: 以当前项目的根目录为起始的路径
比如: "1.txt" "aa\\1.txt"
public class FileDemo03 {
public static void main(String[] args) {
//1.绝对路径
File ff1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
//2.相对路径
File ff2 = new File("1.txt"); //表示当前项目根目录下的1.txt
File ff3 = new File("aa\\1.txt"); //表示当前项目根目录下的aa文件夹里的1.txt
}
}
.File类的判断方法
public boolean exists(); 判断该File对象代表文件和文件夹是否存在
public boolean isDirectory(); 判断该File对象说代表是否是文件夹
public boolean isFile(); 判断该File对象说代表是否是文件
public class FileDemo04 {
public static void main(String[] args) {
//1.创建一个File对象
File ff = new File("1.txt");//相对路径
//2.判断是否存在
boolean b = ff.exists();
System.out.println("是否存在:" + b);
//3.判断是文件呢??还是文件夹呢???
boolean directory = ff.isDirectory();
System.out.println("是文件夹吗?"+directory);
boolean file = ff.isFile();
System.out.println("是文件吗?"+file);
}
}
File类的创建删除方法
public boolean mkdir();创建单级文件夹,返回值表示是否创建成功
public boolean mkdirs();创建多级文件夹,返回值表示是否创建成功
public boolean createNewFile();创建文件,返回值表示是否创建成功
public boolean delete();删除该File对象代表的文件或者空文件夹,返回值表示是否删除成功
public class FileDemo05 {
public static void main(String[] args) throws IOException {
//1.创建一个File对象
File ff = new File("2.txt");
//2.创建文件
boolean b1 = ff.createNewFile();
System.out.println("是否创建成功呢??"+b1);
//3.创建文件夹
boolean b2 = ff.mkdir();
System.out.println("是否创建成功呢??"+b2);
//4.再创建一个File对象
File ff2 = new File("aaa\\bbb\\ccc\\ddd");
boolean b3 = ff2.mkdir();
System.out.println("是否创建成功呢??"+b3);
boolean b4 = ff2.mkdirs();
System.out.println("是否创建成功呢??"+b4);
//5.再创建File对象
File ff3 = new File("2.txt");
boolean b5 = ff3.delete();
System.out.println("是否删除成功呢??"+b5);
}
}
注意: a.mkdir和mkdirs的区别
b.delete方法要么删除文件,要么删除空文件夹,不能删除非空文件夹
File类遍历目录的方法
public String[] list(); 列出当前文件夹下所有直接的文件和文件夹的名字
public File[] listFiles();列出当前文件夹下所有直接的文件和文件夹的File对象
public class FileDemo06 {
public static void main(String[] args) {
//1.创建一个File对象,必须是一个文件夹
File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
//2.list
String[] filenames = ff.list();
for (String filename : filenames) {
System.out.println(filename);
}
//3.listFiles
File[] files = ff.listFiles();
for (File file : files) {
System.out.println(file);
}
}
}
注意: list和listFiles只能列直接的子文件或者子文件夹
二。递归
递归不是Java语言独有的,(基本上很多语言都可以递归)
递归就是:在方法中调用该方法本身(自己调自己)
public class RecursionDemo01 {
public static void main(String[] args) {
method();
}
public static void method(){
System.out.println("method....");
//调用Method自己,这里称为递归
method();
}
}
无限递归(死递归)出现这个错误: StackOverflowError 栈溢出错误!!!
如果要使用递归,必须保证递归有出口(结束的条件)
public static void main(String[] args) {
method1(10);
}
//正常递归(有出口)
public static void method1(int n){
//判断
if (n == 0){
return; //这里就是递归的出口
}
System.out.println("method1...."+n);
//调用Method自己
method1(n-1);
}
注意: 就算递归有出口,还要保证递归在运行到出口之前次数不能太多(太多也会栈内存溢出)
递归求和
需求: 使用递归求1-n的和(开发中不要用)
使用递归三大步骤:
a.先定义一个方法(求和)
b.找规律,调用自己
c.让递归有出口(结束的条件)
public class RecursionDemo02 {
public static void main(String[] args) {
//需求: 使用递归求1-n的和(开发中不要用递归求和)
int sum = getSum(100);
System.out.println(sum);
}
//使用递归
//a.先定义一个方法(求和)
public static int getSum(int n){
//c.让递归有出口(结束的条件)
if (n == 1){
return 1;
}
//b.找规律,调用自己
// 1+2+3..n = (1+2+3..+n-1) + n
// getSum(n) = getSum(n-1) + n
return getSum(n-1) + n;
}
//使用循环
public static int getSum1(int n){
//求和
int sum = 0;
for (int i = 1; i < n+1; i++) {
sum+=i;
}
return sum;
}
}
递归求阶乘
需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用)
使用递归三大步骤:
a.先定义一个方法(求积)
b.找规律,调用自己
c.让递归有出口(结束的条件)
public class RecursionDemo03 {
public static void main(String[] args) {
//需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用递归求和)
int ji = getJi(4);
System.out.println(ji);
}
//使用递归三大步骤:
//a.先定义一个方法(求积)
public static int getJi(int n){
//c.让递归有出口(结束的条件)
if (n == 1) {
return 1;
}
//b.找规律,调用自己
// 1*2*3..*n = (1*2*3..n-1)*n
// getJi(n) = getJi(n-1)*n
return getJi(n-1)*n;
}
//使用循环
public static int getJi1(int n){
int ji = 1;
for (int i = 1; i < n+1; i++) {
ji *= i;
}
return ji;
}
}
文件搜索
需求:
在某个目录中找出所有的.txt文件
某个目录:C:\Users\Administrator\Desktop\temp\aa
public class RecursionDemo04 {
public static void main(String[] args) {
// 需求:
// 在某个目录中找出所有的.txt文件
// 某个目录:C:\Users\Administrator\Desktop\temp\aaa
File fileDir = new File("C:\\Users\\Administrator\\Desktop\\temp\\aa");
//调用
findTxtFile(fileDir);
}
//从指定的目录中搜索txt文件
public static void findTxtFile(File file) {
//1.列出该文件夹下所有的File对象
File[] files = file.listFiles();
//2.遍历列出的数组
for (File f : files) {
//3.判断是否为txt文件
if (f.getName().endsWith(".txt") && f.isFile()) {
System.out.println(f);
}else if (f.isDirectory()){
//那么列出这个f文件夹下的所有.txt文件即可
findTxtFile(f); // 递归!!!
}
}
}
}
三,IO流
I: Input 输入流, 数据从外部设备到程序中,读数据的流
O: Output 输出流, 数据从程序到外部设备,写数据的流
流: 一种比喻,数据传输的过程比喻成流
分类
a.根据流的方向分类:
输入流
输出流
b.根据流中操作的数据类型分类:
字节流 byte
字符流 char
以上两种分类我们可以综合一下:
字节输入流
字节输出流
字符输入流
字符输出流
Java中的IO流
字节输入流: InputStream(顶层父类,抽象类)
字节输出流: OutputStream(顶层父类,抽象类)
字符输入流: Reader(顶层父类,抽象类)
字符输出流 :Writer(顶层父类,抽象类)
技巧: Java中所有的流都会是以上四个流中某一个的子类
而且具体的流的命名是非常有规范的!!
规范: 功能名 +父类名
比如:FileWriter 向文件中写出字符为单位的数据
比如:FileInputStream 从文件读取以字节为单位的数据
1.字节流
输出流:
顶层父类: OutputStream(抽象类)
共性方法:
public void close(); 关闭此流,释放资源
public void flush(); 刷新缓冲区(目前没有!!)
public void write(int b); //一次写一个字节
public void write(byte[] bs);//一次写一个字节数组
public void write(byte[] bs,int startIndex,int len);//一次写一个字节数组的一部分
FileOutputStream类:文件的字节输出流(向文件中写字节数据的)
构造方法
public FileOutputStream(String path);//必须传入文件的路径
public FileOutputStream(File file);//必须传入文件的File对象
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws FileNotFoundException {
//1.创建一个FileOutputStream
FileOutputStream fos = new FileOutputStream("1.txt");
// FileOutputStream fos = new FileOutputStream(new File("1.txt"));
/**
* 构造方法干了三件事!!!
* a.创建对象fos
* b.判断文件是否存在
* 如果存在,会清空文件的内容
* 如果不存在,会自动创建该文件
* c.让对象fos和1.txt绑定
*/
}
}
写字节流数据的三种方法
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream
FileOutputStream fos = new FileOutputStream("1.txt");
//2.向文件中写数据
//a.写一个字节
fos.write(97); // a
//思考:我想要打开之后看到97,怎么办???
// fos.write(57); // 9
// fos.write(55); // 7
//b.写一个字节数组
byte[] bs = {97,98,99,100};
fos.write(bs);
//思考:我想要打开之后看到HelloWorldJavafghjktyuivnm
// byte[] bs1 = "HelloWorldJavafghjktyuivnm".getBytes();
// fos.write(bs1);
//c.写一个字节数组的一部分
byte[] bs2 = {97,98,99,100};
fos.write(bs2,1,2);
}
}
追加续写
只要使用以下构造即可
public FileOutputStream(String path,boolean append);//append表示是否追加
public FileOutputStream(File file,boolean append);//append表示是否追加
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream
FileOutputStream fos = new FileOutputStream("1.txt",true);
//2.写数据
fos.write(97);
}
}
如何换行
只要写文件中写一个代表换行的符号即可
windows \r\n
Linux \n
MacOS \r (MacOSX 也是 \n)
public class FileOutputStreamDemo04 {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream
FileOutputStream fos = new FileOutputStream("1.txt");
//2.写数据
for (int i = 0; i < 10; i++) {
fos.write("java\r\n".getBytes());
// fos.write("\r\n".getBytes());
}
}
}
close 和 flush
public void flush(); 目前我们没用!!(对于字节流输出流没用!!)
public void close(); 关闭流,释放资源
流一旦使用完毕,及时释放资源,别的程序就可以使用该资源了!!!
字节输入流
顶层父类: InputStream(抽象类)
共性方法:
public void close();// 关闭流,释放资源
public int read(); //一次读一个字节
public int read(byte[] bs);//一次读取一个字节数组,返回值表示实际读取的字节个数
FileInputStream类
文件的字节输入流(从文件中读取以字节为单位的数据)
public FileInputStream(String path);//传入文件的路径
public FileInputStream(File file);//传入文件的File对象
public class FileInputStreamDemo01 {
public static void main(String[] args) throws Exception {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
// FileInputStream fis = new FileInputStream(new File("1.txt"));
/**
* 以上构造方法干了三件事!!!
* a.创建对象fis
* b.判断文件是否存在
* 如果存在,什么不干(不清空!!!)
* 如果不存在,会直接抛出异常FileNotFoundException
* c.让fis和1.txt绑定
*/
}
}
读取一个字节
public class FileInputStreamDemo02 {
public static void main(String[] args) throws Exception {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
//2.读数据
//a.一次读取一个字节
//int b = fis.read();
//System.out.println((char) b);
//==============一次读取一个字节的标准循环代码==================
int b = 0;//保存读取到字节
/**
* (b = fis.read()) != -1
* 这句代码干了三件事!!!
* a.先读 fis.read()
* b.赋值 b = 读取字节
* c.判断 b != -1
*/
while ((b = fis.read()) != -1) {
System.out.println((char) b);
}
//4.释放资源
fis.close();
}
}
读取一个字节数组
public class FileInputStreamDemo03 {
public static void main(String[] args) throws Exception {
//1.创建FileInputStream对象
FileInputStream fis = new FileInputStream("1.txt");
//2.读数据
//b.一次读取一个字节数组
//byte[] bs = new byte[4]; //实际开发中 一般1024 或者 其整数倍
//int len = fis.read(bs);
//System.out.println("实际读取到"+len+"个字节");
//System.out.println(new String(bs,0,len));
//===============一次读取一个字节数组的标准循环代码===============
byte[] bs = new byte[4];
int len = 0;
/**
* (len = fis.read(bs)) != -1
* 以上代码干了三件事
* a.先读 fis.read(bs)
* b.赋值 len = 实际读取的个数
* c.判断 len != -1
*/
while ((len = fis.read(bs)) != -1) {
System.out.println(new String(bs,0,len));
}
//3.释放资源
fis.close();
}
}
字节流练习:复制图片
public class CopyFileDemo {
public static void main(String[] args) throws Exception {
//复制文件
//1.源文件G:\uplaod\1.png
FileInputStream fis = new FileInputStream("G:\\upload\\1.png");
//2.目标文件
FileOutputStream fos = new FileOutputStream("copy.png");
//3.复制文件(一次赋值一个字节数组)
byte[] bs = new byte[1024]; // 1KB
int len = 0;
while ((len = fis.read(bs)) != -1) {
fos.write(bs,0,len); // 为了防止最后一次读取时 写入多余的数据
}
//4.释放资源(先开后关)
fos.close();
fis.close();
}
}
一个一个字节复制,一个一个字节数组复制
一次读取一个字节数组的底层原理