File
File类:表示文件和目录路径名的抽象。
File类可以实现文件的创建、删除、重命名、得到路径、创建时间等等,是唯一与文件本身有关的操作类。
public static final String separator | 表示路径分隔符“\” |
---|---|
public File(String pathname) | 构造File类实例,传入路径 |
public boolean createNewFile() | 创建新文件 |
public boolean delete() | 删除文件 |
public boolean isDirectory() | 判断给定的路径是否是文件夹 |
public boolean isFile | 判断给定的路径是否是文件 |
---|---|
public String[] list() | 列出文件夹中的文件 |
public boolean mkdir() | 创建新的文件夹 |
public boolean renameTo(File dest) | 为文件重命名 |
public long length() | 返回文件大小 |
String getPath() | 路径名字符串 |
public class FileDemo01 {
public static void main(String[] args) {
// 表示一个文件或目录,带后缀名的就是文件,不带后缀名是目录
File file = new File("/Users/liuyan/Documents/ppt/kotlin");
// 列出当前目录下所有文件名
String[] fileNames = file.list();
// System.out.print("当前目录下所有文件名:"+ Arrays.toString(fileNames));
File[] files = file.listFiles();
for (File f : files) {
// f.length 文件的长度 f.getName文件的名字
// System.out.println("列出当前目录下的所有文件,以file对象返回:"+f);
System.out.println("相对路径:" + f.getPath());
System.out.println("绝对路径:" + f.getAbsolutePath());
System.out.println("是否是隐藏文件:" + f.isHidden());
System.out.println("是否可读文件:" + f.canRead());
// 毫秒形式展示
Date date = new Date(f.lastModified());
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
System.out.println("文件最后修改时间:" + dateFormat.format(date));
// mkdir 和mkdirs 如果每一及都没有就用mkdirs 只有一层可以用mkdir
File file1 = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/mkdir");
file1.mkdirs();
}
System.out.println("----------------------------");
// 查找目录下以.xlsx结尾的文件
File[] listFiles = file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".xlsx");
}
});
for (File f2 : listFiles) {
System.out.println(f2.getName());
}
}
}
/**
* 在指定的目录中查找文件,查找制定目录下以apk结尾的文件
*/
public class FileDemo02 {
public static void main(String[] args) {
File file = new File("/Users/liuyan/Documents/ppt/kotlin");
findFile(file, ".apk");
}
/**
* 查找文件,原目录,查找的文件
*/
private static void findFile(File target, String dest) {
if (target == null) {
return;
}
// 如果文件是目录
if (target.isDirectory()) {
// 如果目录里面还有目录,递归
File[] files = target.listFiles();
if (files != null) {
for (File f : files) {
findFile(f,dest);
}
}
} else {
// 不是目录,是文件 // toUpperCase() 全转大写 toLowerCase() 全转小写
String name = target.getName().toLowerCase();
// System.out.println("------->>>"+name);
if(name.endsWith(dest)){
System.out.println("---"+target.getAbsolutePath());
}
}
}
}
IO
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。数据在俩设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各个类,更方便直观的进行数据操作。
IO流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
/**
* 字节输入输出流
* 输出流:超类OutputStream,对文件的输出流使用子类FileOutputStream
* 输入流:超类InputStream,对文件的输入流使用子类FileInputStream
*/
public class ByteStreamDemo {
public static void main(String[] args) {
// 输出流
out();
// 输入流
in();
}
private static void out() {
try {
// 1. 确定目标文件
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
// 2.构建一个文件输出流对象
OutputStream os = new FileOutputStream(file);
// 3.输出的内容
String info = "hello world";
// 4.把内容写入文件
os.write(info.getBytes());
// 5.关闭流
os.close();
System.out.println("write success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void in() {
try {
// 1. 确定目标文件
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
FileInputStream in = new FileInputStream(file);
// 读取,一次读取多大,自己设定一个
byte[] bytes = new byte[1024];
StringBuilder sb = new StringBuilder();
// 每次读取的字节长度 -1表示没有
int len = -1;
// 把数据读入到byte数组中,并返回读取的字节数,当不等于-1时,表示读取到数据,等于-1表示文件读完了
while ((len = in.read(bytes)) != -1) {
// 根据读取到的字节数组,再转换为字符串内容,添加到StringBuilder中
// 中文占2个字节,有可能读到中文的一半,会出现乱码,必须写0,len
sb.append(new String(bytes,0,len));
}
System.out.println("打印内容:"+sb);
// 关闭输入流
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流
Writer 写入字符流的抽象类,子类必须实现现有的方法仅有wirte(char[],int,int),flush()和close()。但是,多数子类将重写此处定义的一
些方法,以提供更高的效率和其他功能。与OutputStream一样,对文件操作使用,FileWriter类完成。
Reader 用于读取字符流的抽象类,子类必须实现现有方法read(char[],int,int)和cloase()。但是,多数子类将重写此处定义的方法,以提供更高
的效率。使用FileRead类进行实例化操作。
字节流与字符流区别:
在所有的流操作里,字节永远都是最基础的。任何基于字节的操作都是正确的。无论你的文本文件还是二进制文件。
如果确认流里面只有打印字符的字符,包括英文的的文字,也包括中文,那么可以考虑用字符流。由于编码不同,多字节的字符可能占用多个字节,比如
GBK的汉字占用两个字节,而UTF-8的汉字占用3个字节,所以,字符流是根据指定编码,讲1个或多个字节转换为java里面unicode的字符,然后进行
操作。字符操作一般使用Writer,Reader等,字节操作一般都是InputStream,OutputStream以及各种包装类,比如BufferedInputStream和
BufferedOutputStream等。
不管什么用字节流肯定没问题
/**
* 字符流:解决多字节的文本文件形式
* 字符输出流:Writer,对文件的操作使用子类:FileWriter
* 字符输入流:Reader,对文件的操作使用子类:FileReader
* 每次操作的单位是一个字符
* 文件字符操作流程,自带缓存,默认大小1024字节,在缓存满后,或手动刷新会把缓存清空,或关闭流时,会把数据写入文件
*/
public class CharStreamDemo {
public static void main(String[] args) {
out();
in();
}
private static void out() {
// 1. 确定目标文件
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
try {
Writer out = new FileWriter(file);
String str = "hell,hello";
out.write(str);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void in() {
// 1. 确定目标文件
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
try {
Reader in = new FileReader(file);
int len = -1;
char[] ch = new char[1];
StringBuilder sb = new StringBuilder();
while ((len = in.read(ch)) != -1) {
sb.append(new String(ch,0,len));
}
System.out.println(sb);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件拷贝
/**
* 文件的拷贝
* 从一个输入流中读取数据,然后同时通过输出流写入目标位置
* 一边读,一边写
*/
public class CopyFileDemo {
public static void main(String[] args) {
// 1.原文件,2.目标文件
copy("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt", "/Users/liuyan/IdeaProjects/BiliFengJia/src/b.txt");
}
/**
* src 原文件
* target 目标文件
*/
private static void copy(String src, String target) {
File srcFile = new File(src);
File targetFile = new File(target);
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(targetFile);
byte[] bytes = new byte[1024];
int len = -1;
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) in.close();
if (out != null) out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节字符转换流
转换流:可以将一个字节流转换为字符流,也可以将一个字符流转换为字节流。
OutputStreamWriter:可以将输出的字符流转换为字节流的输出形式
InputStreamReader:将输入的字节流转换为字符流输入形式
/**
* 转换流
* 跟文本相关的时候才会用到转换流,都是用来处理字符的
*/
public class ChangeStreamDemo {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
read(is);
OutputStream out = new FileOutputStream("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
write(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static void write(OutputStream out){
try {
Writer writer = new OutputStreamWriter(out);
writer.write("hello 青岛");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*别人给你个输入流,可能是文件,可能是网络上的文件*/
private static void read(InputStream in) {
try {
Reader reader = new InputStreamReader(in, "utf-8");
char[] cs = new char[1024];
int len = -1;
while ((len = reader.read(cs)) != -1) {
System.out.println(new String(cs, 0, len));
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
缓冲流
对文件或其它目标频繁的读写操作,效率低,性能差。
使用缓冲流的好处是,能够更高效的读写信息,原理是讲数据先缓冲起来,然后一起写入或读取出来。
BufferedInputStream:为另一个输入流添加一些功能,在创建BufferedInputStream时,会创建一个内部缓冲区数组,用于缓冲数据。
BufferedOutputStream:通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符流、数组和行的高效读取。
BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
/**
* 缓存的目的:
* 解决在写入文件操作时,频繁的操作文件所带来的性能降低的问题
* 默认缓存大小 8192 ,8kb,每次写入时,先存储到缓存中的byte数组里,当数组存满时,会把数组
* 中的数据写入文件,并且缓存下标归零
*/
public class BufferStreamDemo {
public static void main(String[] args) {
byteWriter();
byteReader();
}
private static void byteWriter() {
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
try {
OutputStream out = new FileOutputStream(file);
// 构造一个字节缓冲流
BufferedOutputStream bos = new BufferedOutputStream(out);
String info = "缓冲aa";
bos.write(info.getBytes());
bos.close();
// out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void byteReader() {
File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
try {
InputStream in = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(in);
int len = -1;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len));
}
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
字节数组流
ByteArrayInputStream:包含一个内部缓冲区,改缓冲区包含从流中读取的字节。内部计数器跟踪read方法要提供的下一个字节。关闭ByteArrayInputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException。
ByteArrayOutputStream:输出流,其中数据被写入一个byte数组。缓冲区会随着数据的不断写入而自增长。可使用toByteArray()和toString()获取数据。关闭ByteArrayOutputStream无效。此类中的方法在关闭此流后仍可被调用,而不产生任何IOException。
/**
* 字节数组流跟文件没有关系
* 字节数组流,基于内存操作,内部维护着一个字节数组,我们可以利用流的读取机制来处理字符串
* 无需关闭,因为不会报IO异常
*/
public class ByteArrayStreamDemo {
public static void main(String[] args) {
bytreArray();
}
private static void bytreArray() {
// File file = new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/a.txt");
// 把字符串中的字母提出来,包含大小写
String s = "123456abcdEFAGAC%^&*(";
ByteArrayInputStream bis = new ByteArrayInputStream(s.getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int curr = -1;
while ((curr = bis.read()) != -1) {
// 97 -122 大写 65-90
if ((curr >= 65 && curr <= 90) || (curr >= 97 && curr <= 122)) {
bos.write(curr);
}
}
// 无需关闭,字节数组流是基于内存的操作流
System.out.println(bos.toString());
int lenth = bos.toByteArray().length;
System.out.println(lenth);
}
}
文件分割
我们把一个视频文件按照指定大小分割成多个视频文件
public class FileSplitDemo {
public static void main(String[] args) {
File file = new File("/Users/liuyan/Documents/视频/xx视频/ac.mp4");
fileSplitCut(file, 1024 * 1024);
merage();
}
/**
* 文件的分割
* targetFile 要分割的目标文件
* cutsize 每个文件的大小
*/
private static void fileSplitCut(File targetFile, long cutsize) {
if (targetFile == null) return;
// 计算总分割的文件数
int num = targetFile.length() % cutsize == 0 ? (int) (targetFile.length() / cutsize)
: (int) (targetFile.length() / cutsize + 1);
// 我总文件大小是15M多,按照1M分割,这里输出15
System.out.println(num);
try {
// 构造一个文件输入流,总的,一直在读的,读到文件结尾
BufferedInputStream in = new BufferedInputStream(new FileInputStream(targetFile));
BufferedOutputStream out = null; // 读到指定文件大小的时候在生成一个文件
byte[] bytes = null;// 每次要读取的字节数
int len = -1;// 每次读取实际的长度
int count = 0;// 每一个文件要读取的次数 20M 每次读1024,4万多次,1024可以调大一些
// 循环次数为生成文件的个数
for (int i = 0; i < num; i++) {
out = new BufferedOutputStream(new FileOutputStream(new File("/Users/liuyan/IdeaProjects/BiliFengJia/src/" + (i + 1) + "-temp-" + targetFile.getName())));
// 判断每个文件的大小是小于1024还是等于1024
if (cutsize <= 1024) {
bytes = new byte[(int) cutsize];
// 就读一次
count = 1;
} else {
bytes = new byte[1024];
// 这个count 不包括最后一次,有可能cutsize除1024会有余数
count = (int) cutsize / 1024;
}
// 如果整除,就直接搞定
while (count > 0 && (len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush();
count--;
}
// 如果不整除还需要再来一次,比如我15.6M的文件我按照1M来分割15次最后的6 还需要在来一次
// 计算余数,每个文件大小除1024的余数,决定是否要再读取一次
if (cutsize % 1024 != 0) {
bytes = new byte[(int) cutsize % 1024];
len = in.read(bytes);
out.write(bytes, 0, len);
out.flush();
out.close();
}
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
分割后的,按照1M 分割的
image.png
网友评论