一. File
概要:实现将数据从内存中存储到计算机硬盘中,存储方式以File的形式进行存储
File是Java.io包下的类,File类对象既可表示文件,又可表示文件夹
File类只能对文件本身进行操作,不能读写文件里存储的数据,想要操作文件里的数据需要用到io流
1.1 文件的创建
-
文件的创建
-
File文件的相对路径 - 遍历文件
相对路径可以方便文件管理,避免存储到其他盘符,找不到文件
遍历文件夹
1.一级文件夹遍历
#修改文件名
#listFiles只能遍历文件夹下一级目录的内容
public static void main(String[] args)
{
File file=new File("D:\\works");
File[] files = file.listFiles();
for(File f:files)
{
String name = f.getName();
String end = name.substring(name.lastIndexOf("."));
UUID uuid = UUID.randomUUID();
f.renameTo(new File(file,uuid+end));
}
}
2.遍历文件夹下的所有内容—方法递归
-
概念:方法自己调用自己的形式,就叫方法递归。
直接递归,方法内部调用自己;间接递归,方法调用其他方法,其他方法回调自己方法 -
方法递归需要控制终止,不然会进入死循环,导致栈中的方法溢出
-
递归算法的三要素,递归公式:f(n)=f(n-1)*n,递归的终结点:f(1),递归的方向必须走向终结点
//递归累加 public static void main(String[] args) { System.out.println(sum(10)); } public static int sum(int i) { if (i==1) { return i; } else { return sum(i-1)+i; } }
经典案例:猴子吃桃
/** * 猴子吃桃的问题 * 第一天,吃了一半,又多吃了一个;第二天,吃了一半,又多吃了一个....10天后只剩一个了,求桃子的总数 */ public static int test1(int i) { # 根据天数建立方程 f(x)-f(x)/2-1=f(x+1)------->f(x)=2f(x+1)+2 第一天的桃减去吃掉的一半多一个等于第二天的桃子 if(i==10) {return 1;} else {return 2*test1(i+1)+2;}} ```
//根据文件名称查找文件位置-----递归的运用 public class File2 { public static void main(String[] args) throws IOException { fileSearch(new File("F:\\网易云"),"网易云.exe"); } public static void fileSearch(File dir,String name) throws IOException { if (!dir.exists()|| dir.isFile()||dir==null) { return; } File[] files = dir.listFiles(); if (files.length>0&&files!=null) { for (File f:files) { if (f.isFile()) { if (f.getName().contains(name)) { System.out.println("找到了"+f.getAbsolutePath()); Runtime runtime=Runtime.getRuntime(); runtime.exec(f.getAbsolutePath()); } } else { fileSearch(f,name); } } } }
}
```
File类的常见方法,可以参考Java开发文档
二. IO流-字节流
2.1流的基本概念
io流:用于读写数据,可以读写文件,或者网络中的数据
按照流的方向可分为
- 输入流:将磁盘文件或者网络文件读取到内存中
- 输出流:将内存中的数据保存到磁盘
按照流中的最小数据单位可分为
- 字符流 :适合操作纯文本,例如txt、java文件
- 字节流:适合所有文件,例如音频、视频、图片、文本文件的复制转移等
IO流的分类
1.字节输入流
2.字节输出流
3.字符输入流
4.字节输出流
2.2 InputStream
字节输入流,将文件输入到内存,该类是接口类,实现类是FileInputStream
-
read()无参方法,一次读取一个字节
#InputStream的创建 InputStream stream=new FileInputStream(new File("具体文件的路径")) int b; while((b=stream.read())!=-1) { System.out.print((char)b);//InputStream 存储的是字节流,所以,必须转换为字符集 } //read()无参方法只能逐个读取,会占用更大量的系统资源,且使用完毕需要关闭流,close()方法 //read()方法,当字节流读取完所有的字节后,会返回-1 ```
-
read( byte[ ] b)有参方法,一次读取多个字节
//read(byte[] buffer),一次性读取多个字节,性能高,但是读取汉字会出现乱码 InputStream stream=new FileInputStream(new File("具体文件的路径")) byte[] buffer=new byte[3]; int len=stream.read(buffer);//将读取到的字节放入buffer数组,返回数为读取到的数值总数,读取到的内容不能超过数组长度。 String str=new String(buffer,0,len);//buffer数组,从第0位开始,读取len长度的数据转为字符串 int len=stream.read(buffer);//当多次向同一个字节数组添加数据时,且字节数组长度不够用,后者会覆盖前者
-
一次读取所有字节
//1.定义一个和文件大小一样的字节数组,存放数据 InputStream is=new FileInputStream("文件地址"); File f=new File("文件地址"); long size=f.length(); byte[] buffer=new byte[(int) size]; is.read(buffer); //2.调用readAllBytes方法直接读取所有的 InputStream is=new FileInputStream("文件地址"); byte[] buffer=is.readAllBytes(); System.out.print(new String(buffer));
字节输入流的缺点,如果文件过大,会出现内存溢出
2.3 OutputStream
将内存中的数据写到文件中,该类为接口类,实现类为FileOutputStream
//通过io流复制文件
InputStream inputStream=new FileInputStream("D:\\works\\test3\\1.jpg");//读取文件流
OutputStream outputStream=new FileOutputStream("D:\\test1\\test2\\2.jpg");//写入文件流,文件名必须自取
long i = new File("D:\\works\\test3\\1.jpg").length();//获取文件字节数
byte[] bytes=new byte[(int) i];//创建对应长度的字节数组
int len;
inputStream.read(bytes);//读文件,将读取的数据放入字节数组
outputStream.write(bytes);//写文件,将数组中的文件写道指定的文件夹中
outputStream.close();
inputStream.close();
2.4 IO流资源的释放
try
{//执行语句
}
catch(Exception e)
{//语句出现异常捕获异常
}
finally
{//不管语句正确与否,一定会执行
}
需要注意的是,不能在finall方法体内输入return,不然try方法体就不能执行了
try…catch…finally
try-with-resource
将连接的流资源放在try的小括号内,去掉原有的finally,当调用完成,方法会自动释放关闭流
底层原理,输入输出流实现了Closeable接口,只要实现了该接口就能算作资源类,且Closeable中定义了资源关闭方法close(),所以当使用try-catch-resource时,资源使用完毕后会自动释放
3.IO流–字符流
字符输入流-FileReader,原理和字节输入流一致,只是读取的每个数据都会被当作字符看待
字符输出流常用的方法
注意:字符输出流写出数据后,必须刷新,或者关闭流,写入的数据才能生效
flush()方法进行刷新;close()关闭后等于自动刷新
4.缓冲流
4.1字节缓冲流
原理:字节缓冲输出输入流自带了8KB缓冲池,字节缓冲流每读写一次,就往缓冲池放入8KB的字节,使用缓冲流是为了提高读写的性能,缓冲池在内存中,内存读写的效率比外存高
// 缓冲字节流拷贝视频,视频、音频等资源文件需要用字节流读写
public static void test2()
{
try (
BufferedInputStream bufferedInputStream= new BufferedInputStream(new FileInputStream("D:\\电影直播\\video_230801_192356.mp4"));
BufferedOutputStream outputStream= new BufferedOutputStream(new FileOutputStream("D:\\电影直播\\1.mp4"));
)
{
long start = System.currentTimeMillis();
long ln=0;
byte [] bytes=new byte[1024];
while ((ln=bufferedInputStream.read(bytes))!=-1)
{
outputStream.write((int) ln);
}
long end = System.currentTimeMillis();
System.out.println((end-start)/1000+"s");
}catch (Exception e)
{
}
}
简单字节流和缓冲字节流,在调用有参字节的读写时,字节数组长度越大,读写性能越好
4.2字符缓冲流
作用:提高字符流的读写效率,自带8KB的缓冲池,缓冲池在内存中,字符缓冲流每读写一次,就往缓冲池放入8KB的字符,内存读写的效率比外存高
字符缓冲输入流
- 创键字符缓冲输入流
- BufferedReader类提供了一个特有的方法,读取一行字符,readLine(),没有值时就返回null
字符缓冲输出流
- public BufferedWriter(Writer r),把低级字符输出流包装成一个高级的缓冲字符输出流管道,提高字符流写的效率
- 字符缓冲输出流新增的功能:换行,public void newLine()
5. IO流-转换流
如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取的文本文件会出现乱码
解决方法:字符转换流
5.1字符输入转换流—InputStreamReader
//解决乱码的思路
1.先将拿到文件的字节流,然后通过字符转换流的构造方法,将字节流的编码格式改成文件对应的编码格式,如GBK
public InputStreamReader(InputStream is,String charset)
例如:
InputStream is=new FileInputStream("文件地址");
Reader isr=new InputStreamReader(is,"GBK");
BufferReader br=new BufferReader(isr);
5.2 字符输出转换流
//实现的思路
1.拿到原始的字节输入流
2.通过字符输出转换流的构造方法,传入字节流,并将字符输出流编码格式改成需要的格式
public OutputStreamWrite(OutputStream os,String charset)
案例
OutputStream os=new FileOutputStream("文件地址");
Writer osw=new OutputStreamWriter(os,"GBK");
BufferWrite bw=new BufferWriter(osw);
bw.write("123你好");
//写入后要生效的话记得关闭流或刷新流
6.打印流
6.1PrintStream,字节打印流
构造器和方法
6.2PrintWriter,字符打印流
6.3 流的重定向
System.out.println()就是采用打印流的放法,将数据输出在控制台
PrintStream ps=new PrintStream("文件路径");
System.setOut(ps);
//输出的内容被重定向到指定的文件路径中
7.IO流-数据流
用于通信,可以存储数据的类型,根据类型读取数据
需要注意的是,读取数据的时候,需要按照数据类型的排序进行读取
8.IO流-序列化流
将java对象写入到文件中,即序列化。将java对象读取出来,即反序列化
如果想要一次性序列化多个对象的话,直接对集合进行序列化即可,ArrayList集合已经实现了序列化接口
序列化
- 需要自定义一个类,并实现序列化接口Serializable
- 序列化流的创建
- 将序列化文件写入
oss.writeObject(new User("张三",23,"男"))
反序列化
在进行序列化的时候,某个熟悉不想被展示出来,可以用transient
修饰属性,这样该属性就不会参与反序列化
9.IO流-io框架(重点)
Commons-io框架
,用框架可以直接省略以上的所有内容