1,File
File:代表文本
文件是非常重要的存储方式,在计算机硬盘中
即便断电,或者程序终止了,存储在硬盘文件中的数据也不会丢失
File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)
(1)File的功能
1,获取文件信息(大小,文件名,修改时间)
2,判断文件的类型
3,创建文件/文件夹
4,删除文件/文件夹
5,...
注意:File类只能对文件本身进行操作,不能读写文件里面存储的数据
(1)创建File对象
构造器 | 说明 |
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent,String child) | 根据父路径和子路径名字创建文件对象 |
public File(File parent,String child) | 根据父路径对应文件对象和子路径名字创建文件对象 |
路径分隔符:/或者\\,不可以为\
File a=new File("C:\\Program Files (x86)\\微信图片_20231016191644.jpg");
File a1=new File("C:"+File.separator+"Program Files (x86)"+File.separator+"微信图片_20231016191644.jpg");
File a=new File("C:/Program Files (x86)/微信图片_20231016191644.jpg");
注意:File对象可以指代一个不存在的文件路径
我现在要定位的文件是在模块中,应该怎么定位呢?
绝对路径:带盘符的
C:\\Users\\Lenovo\\IdeaProjects\\two\\com\\ja\\app\\Test4.java
相对路径:不带盘符,默认直接去工程下寻找文件
IdeaProjects\\two\\com\\ja\\app\\Test4.java
注意:
File对象既可以代表文件、也可以代表文件夹
File封装的对象仅仅是一个路径名,这个路径可以是存在的,也允许是不存在的
(2)File提供的判断文件类型、获取文件信息功能
方法名称 | 说明 |
public boolean exists() | 判断当前文件对象,对应的文件路径是否存在,存在返回true |
public boolean isFile() | 判断当前文件对象指代的是否是文件,是文件返回true,反之 |
public boolean isDirectory() | 判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之 |
public String getName() | 获取文件的名称(包含后缀) |
public long length() | 获取文件的大小,返回字节个数 |
public long lastModified() | 获取文件的最后修改时间 |
public String getPath() | 获取创建文件对象时,使用的路径 |
public String getAbsolutePath() | 获取绝对路径 |
(3)创建文件,删除文件
1)File创建文件的功能
方法名称 | 说明 |
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 只能创建一级文件夹 |
public boolean mkdirs() | 可以创建多级文件夹 |
2)File删除文件的功能
方法名称 | 说明 |
public boolean delete() | 删除文件、空文件夹 |
注意:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站
(4)遍历文件夹
方法名称 | 说明 |
public String[] list() | 获取当前日录下所有的“一级文件名称”到一个字符串数塑中去返回 |
public File[] listFiles() | 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点) |
File f1=new File("D:\\Drivers");
String[]names=f1.list();
for (String name:names) {
System.out.println(name);
}
File[]files=f1.listFiles();
for (File file:files) {
System.out.println(file.getAbsolutePath());
}
使用listFiles方法时的注意事项:
1,当主调是文件,或者路径不存在时,返回null
2,当主调是空文件夹时,返回一个长度为0的数组
3,当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
4,当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
5,当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
2,方法递归
方法递归:递归是一种算法,在程序设计语言中广泛应用
从形式上说:方法调用自身的形式称为方法递归( recursion)
(1)递归的形式
1)直接递归:方法自己调用自己
2)间接递归:方法调用其他方法,其他方法又回调方法自己
使用方法递归时需要注意的问题;
递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出错误
(2)递归算法三要素
递归的公式: f(n) = f(n-1)*n;
递归的终结点:f(1);
递归的方向必须走向终结点;
3,字符集
标准ASCII字符集:
ASCI(American Standard Code for Information Interchange):美国信息交换标准代码,包括了英文、符号等
标准ASCI使用1个字节存储一个字符,首位是0,总共可表示128个字符,对美国佬来说完全够用
GBK(汉字内码扩展规范,国标)
汉字编码字符集,包含了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储
注意:GBK兼容了ASCIl字符集
GBK规定:汉字的第一个字节的第一位必须是1
Unicode字符集(统一码,也叫万国码)UTF-32
Unicode是国际组织制定的,可以容纳世界上所有文字、符号的字符集
4个字节一个字符 有容乃大
UTF-8
是Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节
英文字符、数字等只占1个字节(兼容标准ASCIl编码),汉字字符占用3个字节
UTF-8编码方式(二进制) |
0xxxxxxx(ASCII码) |
110xxxxx 10xxxxxx |
1110xxxx 10xxxxxx 10xxxxxx |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
注意:技术人员在开发时都应该使用UTF-8编码
ASCII字符集:只有英文、数字、符号等,占1个字节
GBK字符集:汉字占2个字节,英文、数字占1个字节
UTF-8字符集:汉字占3个字节,英文、数字占1个字节
注意1:字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码
注意2:英文,数字一般不会乱码,因为很多字符集都兼容了ASCII编码
Java代码完成对字符的编码
String提供了如下方法 | 说明 |
byte[] getBytes() | 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
Java代码完成对字符的解码
String提供了如下方法 | 说明 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的String |
String(byte[] bytes,String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的String |
2进制中首位为1为负数
4,IO流
IO流(输入输出流):读写数据
用于读写数据的(可以读写文件,或网络中的数据...)
概述:I指Input,称为输入流:负责把数据读到内存中去
O指Output,称为输出流:负责写数据出去
怎么学IO流?
1、先搞清楚IO流的分类、体系
2、再挨个学习每个IO流的作用、用法
IO流的四大流:
字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流。
字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。
(1) FileInputStream(文件字节输入流)
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去
构造器 | 说明 |
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通 |
方法名称 | 说明 |
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1. |
public int read(byte[ ] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1 |
//源代码
InputStream is=new FileInputStream(new File("D:\\LenovoQMDownload\\SoftMgr"));
//简化代码,推荐使用
InputStream is=new FileInputStream(new File("D:\\LenovoQMDownload\\SoftMgr"));
int b;
while((b=is.read())!=-1){
System.out.println((char) b);
}
//读取数据的性能很差
//读取数字会乱码,无法避免
//流使用完毕之后,必须关闭释放系统资源
is.close();
注意事项:使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码
FileInputStream is=new FileInputStream("D:\\code\\aaa.txt");
byte[]buffer=new byte[3];
int len ;//记住读取了多少个字节
while((len=is.read(buffer))!=-1){
//读取多少,倒出多少
String rs=new String(buffer,0,len);
System.out.print(rs);
}
//性能更好
//但不能避免汉字乱码问题
is.close();//关闭流
注意事项:使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码
文件字节输入流:一次读取完全部字节
方式一:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节
方法名称 | 说明 |
public int read (byte[ ]buffer) | 每次用一个字节数组去读取,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1 |
方式二:Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回
方法名称 | 说明 |
public byte[] readAllBytes () throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
问题:
如果文件过大,创建的字节数组也会过大,可能引起内存溢出
字节流适合做数据的转移,如:文件复制等
读写文本内容更话合用:字符流
(2) FileOutputStream(文件字节输出流)
构造器 | 说明 |
public FileOutputStrean(File file) | 创建字节输出流管道与源文件对象接通 |
public FileoutputStream(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileoutputStream(File file, boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
public void write(int a) | 写一个字节出去 |
public void write(byte[ ] buffer) | 写一个字节数组出去 |
public void write(byte[ ] buffer , int pos , int len) | 写一个字节数组的一部分出去 |
public void close( ) throws IOException | 关闭流 |
OutputStream os=new FileOutputStream("two/com/add.txt",append);//带append为在原来数据的基础上添加
os.write(97);
os.write('b');
byte[] bytes="我爱你中国abc".getBytes();
os.write(bytes);
//截取一部分
os.write(bytes,0,15);
//换行符
os.write("/r/n",getbytes);
os.close();
字节流非常适合做一切文件的复制操作
任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题
(3)释放资源
1)try-catch-finally
格式:
try{
...
...
}catch(IOException e){
e.printStackTrace();
}finaly{
}
finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止
不能在finally中返回数据
作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法)
//专业代码
import java.io.*;
public class Test1 {
public static void main(String[] args) {
InputStream is=null;
OutputStream os=null;
try {
System.out.println(10/0);
is =new FileInputStream("two\\com\\add.txt");
os =new FileOutputStream("two\\com\\add.txt");
System.out.println(10/0);
byte[] buffer=new byte[1024];//1KB
int len;//记住每次读取了多少个字节
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
System.out.println("复制完成!!");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (os!=null)os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (is!=null)is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2)try-with-resourse
try(定义资源1;定义资源2;...){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
该资源使用完毕后,会自动调用其close()方法,完成对资源的释放
import java.io.*;
public class Test1 {
public static void main(String[] args) {
try (
InputStream is =new FileInputStream("two\\com\\add.txt");
OutputStream os =new FileOutputStream("two\\com\\add.txt");
){
byte[] buffer=new byte[1024];//1KB
int len;//记住每次读取了多少个字节
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
System.out.println("复制完成!!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意事项:
小括号()里只能放资源对象(流对象)
用完之后,会被自动调用其close方法定成资源的释放操作
资源的定义:
资源都是会实现AutoCloseable接口