java IO
IO:记住一句话,以程序为中心,进入程序--读取(输入流);从程序中出来--输出流
输入流:数据源到程序(InputStream、Reader读进来)
输出流:程序到目的地(OutputStream、Writer写出去)
一、流分类
字节流:按照字节读取数据(InputStream、OutputStream)
字符流:按照字符读取数据(Reader、Writer) ,因为文件 编码的不同,从而有了对字符进行高效操作的字符流对象。
原理:底层还是基于字节流操作,自动搜寻了指定的码表。
字节流:
字符流:
二、File类
2.1 常用方法
API | 说明 | |
---|---|---|
pathSeparator separator | 路径 | 路径分隔符 |
File(String parent,String child) File(File parent, String child) File(String name) | 构造器 没有盘符以user.dir作为相对目录 | |
getName() getPath() getAbsolutePath() getParent() | 文件名、路径名 | |
exists() isFile() isDirectory() | 判断状态 | |
length() | 文件长度 | |
createNewFile() delete() | 创建新文件 删除文件 |
mkdir() mkdirs() | 创建目录,如果父目录链不存在一同创建 | ||
---|---|---|---|
list() | 下级名称 | ||
listFiles() | 下级文件 | ||
listRoots() | 根路径 |
2.2 IO流
2.2.1 四大抽象类
抽象类 | 说明 | 常用方法 |
---|---|---|
InputStream | 字节输入流的父类,数据单位为字节。 | • int read()• void close() |
OutputStream | 字节输出流的父类,数据单位为字节。 | • void write(int)• void flush()• void close() |
Reader | 字符输入流的父类,数据单位为字符。 | • int read()• void close() |
Writer | 字符输出流的父类,数据单位为字符。 | • void write(String)• void flush()• void close() |
2.3 构建File对象的三种方式
//1、构建File对象
String src="D:/java/IO/io.png";
File src =new File(path);
System.out.println(src.length());
//2.父路径+子文件名
src =new File("D:/java/IO","io.png");//严格的父路径+子文件名
src =new File("D:/java","/IO/io.png");//只要路径能拼接成功就行,无论怎么分割
//3.父对象+子文件名
src =new File(new File("D:/java/IO"),"io.png");
2.4 文件操作
//文件状态
src = new File("xxx");
if(null==src||!src.exists()){
System.out.println("文件不存在");
}else{
if(src.isFile()){
System.out.println("文件操作");
}else{
System.out.println("文件夹操作");
}
}
//文件长度 length() ---字节数
File src =new File("D:/java/IO/io.png");
System.out.println(src.length());
//创建文件 删除文件
//不是文件夹
File src =new File("D:/java/IO/io.png");
boolean flag=src.createNewFile(); //不存在创建,存在创建成功
System.out.prinln(flag);
//删除文件
flag =src.delete();
//------------------文件夹操作
//mkdir() :必须保证上一级目录存在,
//mkdirs() : 不必保证上一级目录是否存在,若不存在 就会自动创建,(推荐使用)
//list():列出下一级名称
//listFiles(): 列出下一级对象 list()和listFiles()如果想列出所有下一级(仅仅一级)的所有文件或者对象需要遍历
//listRoots():根路径
//---打印子孙级目录和文件名称
main()
File src = new File("D:/java/IO/io.png");
printName(src,0);
//printName函数名
public static void printName(File src,int deep){
for(int i=0;i<deep;i++){
System.out.print("-"); //有几层打印几个
}
//打印名称
System.out.println(src.getName);
if(null==src||!src.exists()){
return;
}else if(src.isDirectory()){//目录
for(File s:src.listFiles()){
printName(s,deep+1);//递归体
}
}
}
//统计文件夹的大小
private static long len=0;
public static void count(File src){
//获取大小
if(null!=src&&src.exists()){
if(src.isFile()){//大小
len+=src.length();
}else {//子孙级
for(File s:src.listFiles()){
count(s); //递归
}
}
}
}
三、 IO流操作的基本步骤
1、创建源
2、选择流
3、操作流
4、释放资源
//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (读取)
int temp ;
while((temp=is.read())!=-1) {
System.out.println((char)temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
3.1 FileInputStream、FileOutputStream
FileInputStream:通过字节的方式读取文件,适合读取所有 类型的文件(图像、视频等), 全字符请考虑FileReader
FileOutputStream:通过字节的 方式写出或追加数据到文件, 适合所有类型的文件(图像、视 频等),全字符请考虑 FileWriter
以下实例完成文件拷贝:
//文件字节输入流
//1、创建源
File src = new File("abc.txt");
//2、选择流
InputStream is =null;
try {
is =new FileInputStream(src);
//3、操作 (分段读取)
byte[] flush = new byte[1024*10]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
//字节数组-->字符串 (解码)
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//文件字节输出流 --(文件拷贝)
//1、创建源
File dest = new File("dest.txt");
//2、选择流
OutputStream os =null;
try {
os = new FileOutputStream(dest,true);
//3、操作(写出)
String msg ="IO is so easy\r\n";
byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码)
os.write(datas,0,datas.length);
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
文件的拷贝:
/**
* 文件的拷贝
* 思考: 利用递归 制作文件夹的拷贝 :先打开的后关闭
* @param srcPath
* @param destPath
*/
public static void copy(String srcPath,String destPath) {
//1、创建源
File src = new File(srcPath); //源头
File dest = new File(destPath);//目的地
//2、选择流
InputStream is =null;
OutputStream os =null;
try {
is =new FileInputStream(src);
os = new FileOutputStream(dest);
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源 分别关闭 先打开的后关闭
try {
if (null != os) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void copy2(String srcPath,String destPath) {
//1、创建源
File src = new File(srcPath); //源头
File dest = new File(destPath);//目的地
//2、选择流
try(InputStream is=new FileInputStream(src);
OutputStream os = new FileOutputStream(dest); ) {
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 FileReader&FileWriter
FileReader :通过字符的方式读取文件,仅适合字符文件
FileWriter :通过字节的方式写出或追加数据到文件中,仅适合字符文件
//文件字符输入流
//1、创建源
File src = new File("abc.txt");
//2、选择流
Reader reader =null;
try {
reader =new FileReader(src);
//3、操作 (分段读取)
char[] flush = new char[1024]; //缓冲容器
int len = -1; //接收长度
while((len=reader.read(flush))!=-1) { //将reader引用中的数据读到flush数组中,并返回flush的长度
//字符数组-->字符串
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//文件字符输出流
//1、创建源
File dest = new File("dest.txt");
//2、选择流
Writer writer =null;
try {
writer = new FileWriter(dest);
//3、操作(写出)
//写法一
// String msg ="IO is so easy\r\n尚学堂欢迎你";
// char[] datas =msg.toCharArray(); // 字符串-->字符数组
// writer.write(datas,0,datas.length);
//写法二
/*String msg ="IO is so easy\r\n尚学堂欢迎你";
writer.write(msg);
writer.write("add");
writer.flush();*/
//写法三
writer.append("IO is so easy\r\n").append("尚学堂欢迎你");
writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
3.3 ByteArrayInputStream&ByteArrayOutputStream
字节数组流 特点:不用关闭流
注意:
<u>字节数组输入流:</u>1、创建源 : 字节数组 不要太大 2、选择流 3、操作 4、释放资源: 可以不用处理
字节数组输出流:1 创建源 : 内部维护 2、选择流 : 不关联源 3、操作(写出内容) 4、释放资源 :可以不用
//字节数组输入流
//1、创建源
byte[] src = "talk is cheap show me the code".getBytes();//字符串转为字节数组
//2、选择流
InputStream is =null;
try {
is =new ByteArrayInputStream(src);
//3、操作 (分段读取)
byte[] flush = new byte[5]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
//字节数组-->字符串 (解码)
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//字节数组输出流
//1、创建源
byte[] dest =null;
//2、选择流 (新增方法)
ByteArrayOutputStream baos =null;
try {
baos = new ByteArrayOutputStream();
//3、操作(写出)
String msg ="show me the code";
byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码)
baos.write(datas,0,datas.length);
baos.flush();
//获取数据
dest = baos.toByteArray(); //将流转化为数组
System.out.println(dest.length +"-->"+new String(dest,0,baos.size()));
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != baos) {
baos.close();
}
} catch (Exception e) {
}
}
3.4 缓冲流(字节缓冲和字符缓冲)
3.4.1 (字节缓冲流)BufferedInputStream&BufferedOutputStream
用缓冲流对原来的流进行封装
//字节文件输入流 加入缓冲流
File src = new File("abc.txt");
//2、选择流
InputStream is =null;
try {
is =new BufferedInputStream(new FileInputStream(src));
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
//字节数组-->字符串 (解码)
String str = new String(flush,0,len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//字节数组输出流 加入缓冲流
//1、创建源
File dest = new File("dest.txt");
//2、选择流
OutputStream os =null;
try {
os =new BufferedOutputStream( new FileOutputStream(dest));
//3、操作(写出)
String msg ="IO is so easy\r\n";
byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码)
os.write(datas,0,datas.length);
os.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
3.4.2 (字符缓冲流)BufferedReader&BufferedWriter
//文件字符输入流 --加入缓冲流
//1、创建源
File src = new File("abc.txt");
//2、选择流
BufferedReader reader =null;
try {
reader =new BufferedReader(new FileReader(src));
//3、操作 (分段读取)
String line =null;
while((line=reader.readLine())!=null) {
//字符数组-->字符串
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=reader) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//文件字符输出流 --加入缓冲流
//1、创建源
File dest = new File("dest.txt");
//2、选择流
BufferedWriter writer =null;
try {
writer = new BufferedWriter(new FileWriter(dest));
//3、操作(写出)
writer.append("IO is so easy");
writer.newLine();
writer.append("尚学堂欢迎你");
writer.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//4、释放资源
try {
if (null != writer) {
writer.close();
}
} catch (Exception e) {
}
}
3.5 转换流 InputStreamReader&OutputStreamWriter
转换流: InputStreamReader OutputStreamWriter
1、以字符流的形式操作字节流(纯文本的)
2、指定字符集
public class ConvertTest {
public static void main(String[] args) {
//操作System.in 和System.out
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
//循环获取键盘的输入(exit退出),输出此内容
String msg ="";
while(!msg.equals("exit")) {
msg = reader.readLine(); //循环读取
writer.write(msg); //循环写出
writer.newLine();
writer.flush(); //强制刷新
}
}catch(IOException e) {
System.out.println("操作异常");
}
}
}
//example 2
public class ConvertTest02 {
public static void main(String[] args) {
try(BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new URL("http://www.baidu.com").openStream(),"UTF-8"));
BufferedWriter writer =
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("baidu.html"),"UTF-8"));){
//3、操作 (读取)
String msg ;
while((msg=reader.readLine())!=null) {
//System.out.println(msg);
writer.write(msg); //字符集不统一不够出现乱码
writer.newLine();
}
writer.flush();
}catch(IOException e) {
System.out.println("操作异常");
}
}
public static void test2() {
//操作网络流 下载百度的源代码
try(InputStreamReader is =
new InputStreamReader(new URL("http://www.baidu.com").openStream(),"UTF-8");){
//3、操作 (读取)
int temp ;
while((temp=is.read())!=-1) {
System.out.print((char)temp);
}
}catch(IOException e) {
System.out.println("操作异常");
}
}
public static void test1() {
//操作网络流 下载百度的源代码
try(InputStream is =new URL("http://www.baidu.com").openStream();){
//3、操作 (读取)
int temp ;
while((temp=is.read())!=-1) {
System.out.print((char)temp); //字节数不够出现乱码
}
}catch(IOException e) {
System.out.println("操作异常");
}
}
}
3.6 数据流 DataInputStream&DataOutputStream
数据流: 1、写出后读取
2、读取的顺序与写出保持一致
public static void main(String[] args) throws IOException {
//写出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作数据类型 +数据
dos.writeUTF("编码辛酸泪");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
System.out.println(datas.length);
//读取
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dis.readUTF();
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(flag);
}
```
3.7 对象流
对象流:
1、写出后读取
2、读取的顺序与写出保持一致
3、不是所有的对象都可以序列化Serializable
* 对象流: 1、写出后读取 2、读取的顺序与写出保持一致 3、不是所有的对象都可以序列化Serializable
*
* ObjectOutputStream ObjectInputStream
*
* @author TW
*
*/
public class ObjectTest02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 写出 -->序列化
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("obj.ser")));
// 操作数据类型 +数据
oos.writeUTF("编码辛酸泪");
oos.writeInt(18);
oos.writeBoolean(false);
oos.writeChar('a');
// 对象
oos.writeObject("谁解其中味");
oos.writeObject(new Date());
Employee emp = new Employee("马云", 400);
oos.writeObject(emp);
oos.flush();
oos.close();
// 读取 -->反序列化
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("obj.ser")));
// 顺序与写出一致
String msg = ois.readUTF();
int age = ois.readInt();
boolean flag = ois.readBoolean();
char ch = ois.readChar();
System.out.println(flag);
// 对象的数据还原
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = ois.readObject();
if (str instanceof String) {
String strObj = (String) str;
System.out.println(strObj);
}
if (date instanceof Date) {
Date dateObj = (Date) date;
System.out.println(dateObj);
}
if (employee instanceof Employee) {
Employee empObj = (Employee) employee;
System.out.println(empObj.getName() + "-->" + empObj.getSalary());
}
ois.close();
}
3.8 随机读写流
public static void main(String[] args) throws IOException {
//分多少块
File src = new File("p.png");
//总长度
long len = src.length();
//每块大小
int blockSize =1024;
//块数: 多少块
int size =(int) Math.ceil(len*1.0/blockSize); //向上取整
System.out.println(size);
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
System.out.println(i+"-->"+beginPos +"-->"+actualSize);
split(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
* @param i
* @param beginPos
* @param actualSize
* @throws IOException
*/
public static void split(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("p.png"),"r");
RandomAccessFile raf2 =new RandomAccessFile(new File("dest/"+i+"p.png"),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容 实际大小》每段规定应读取长度,按规定来,否则else
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
功能模块实现:文件分割:
/**
* 面向对象思想封装 分割
*
*/
public class SplitFile {
//源头
private File src;
//目的地(文件夹)
private String destDir;
//所有分割后的文件存储路径
private List<String> destPaths;
//每块大小
private int blockSize;
//块数: 多少块
private int size;
public SplitFile(String srcPath,String destDir) {
this(srcPath,destDir,1024);
}
public SplitFile(String srcPath,String destDir,int blockSize) {
this.src =new File(srcPath);
this.destDir =destDir;
this.blockSize =blockSize;
this.destPaths =new ArrayList<String>();
//初始化
init();
}
//初始化
private void init() {
//总长度
long len = this.src.length();
//块数: 多少块
this.size =(int) Math.ceil(len*1.0/blockSize);
//路径
for(int i=0;i<size;i++) {
this.destPaths.add(this.destDir +"/"+i+"-"+this.src.getName());
}
}
/**
* 分割
* 1、计算每一块的起始位置及大小
* 2、分割
* @throws IOException
*/
public void split() throws IOException {
//总长度
long len = src.length();
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
splitDetail(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
* @param i
* @param beginPos
* @param actualSize
* @throws IOException
*/
private void splitDetail(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(this.src,"r");
RandomAccessFile raf2 =new RandomAccessFile(this.destPaths.get(i),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
/**
* 文件的合并
* @throws IOException
*/
public void merge(String destPath) throws IOException {
//输出流
OutputStream os =new BufferedOutputStream( new FileOutputStream(destPath,true));
Vector<InputStream> vi=new Vector<InputStream>();
SequenceInputStream sis =null;
//输入流
for(int i=0;i<destPaths.size();i++) {
vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
}
sis =new SequenceInputStream(vi.elements());
//拷贝
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=sis.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
sis.close();
os.close();
}
public static void main(String[] args) throws IOException {
SplitFile sf = new SplitFile("src/com/sxt/io/SplitFile.java","dest") ;
sf.split();
sf.merge("aaa.java");
}
}
四、组件使用 CommonsIO---FileUtils使用
用处:
• writing to a file
• reading from a file
• make a directory including parent directories
• copying files and directories
• deleting files and directories
• converting to and from a URL
• listing files and directories by filter and extension
• comparing file content
• file last changed date
• calculating a checksum
//1、大小
//文件大小
long len =FileUtils.sizeOf(new File("src/com/sxt/commons/CIOTest01.java"));
System.out.println(len);
//目录大小
len = FileUtils.sizeOf(new File("D:/java300/IO_study04"));
System.out.println(len);
2//
/**
* 列出子孙级
*
*/
public class CIOTest02 {
public static void main(String[] args) {
Collection<File> files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
EmptyFileFilter.NOT_EMPTY, null);
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
System.out.println("---------------------");
files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
EmptyFileFilter.NOT_EMPTY, DirectoryFileFilter.INSTANCE);
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
System.out.println("---------------------");
files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
new SuffixFileFilter("java"), DirectoryFileFilter.INSTANCE);//sufficient后缀
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
System.out.println("---------------------");
files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
FileFilterUtils.or(new SuffixFileFilter("java"),
new SuffixFileFilter("class"),EmptyFileFilter.EMPTY), DirectoryFileFilter.INSTANCE);
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
System.out.println("---------------------");
files =FileUtils.listFiles(new File("D:\\java300\\IO_study04"),
FileFilterUtils.and(new SuffixFileFilter("java"),
EmptyFileFilter.NOT_EMPTY), DirectoryFileFilter.INSTANCE);
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
}
//3/**
* 读取内容
*
*/
public class CIOTest03 {
public static void main(String[] args) throws IOException {
//读取文件
String msg =FileUtils.readFileToString(new File("emp.txt"),"UTF-8");
System.out.println(msg);
byte[] datas = FileUtils.readFileToByteArray(new File("emp.txt"));
System.out.println(datas.length);
//逐行读取
List<String> msgs= FileUtils.readLines(new File("emp.txt"),"UTF-8");
for (String string : msgs) {
System.out.println(string);
}
LineIterator it =FileUtils.lineIterator(new File("emp.txt"),"UTF-8");
while(it.hasNext()) {
System.out.println(it.nextLine());
}
}
}
//4/**
* 写出内容
*
*/
public class CIOTest04 {
public static void main(String[] args) throws IOException {
//写出文件
FileUtils.write(new File("happy.sxt"), "学习是一件伟大的事业\r\n","UTF-8");
FileUtils.writeStringToFile(new File("happy.sxt"), "学习是一件辛苦的事业\r\n","UTF-8",true);
FileUtils.writeByteArrayToFile(new File("happy.sxt"), "学习是一件幸福的事业\r\n".getBytes("UTF-8"),true);
//写出列表
List<String> datas =new ArrayList<String>();
datas.add("马云");
datas.add("马化腾");
datas.add("弼马温");
FileUtils.writeLines(new File("happy.sxt"), datas,"。。。。。",true);
}
}
//5/**
* 拷贝
*
*/
public class CIOTest05 {
public static void main(String[] args) throws IOException {
//复制文件
//FileUtils.copyFile(new File("p.png"),new File("p-copy.png"));
//复制文件到目录
//FileUtils.copyFileToDirectory(new File("p.png"),new File("lib"));
//复制目录到目录
//FileUtils.copyDirectoryToDirectory(new File("lib"),new File("lib2"));
//复制目录
//FileUtils.copyDirectory(new File("lib"),new File("lib2"));
//拷贝URL内容
//String url = "https://pic2.zhimg.com/v2-7d01cab20858648cbf62333a7988e6d0_qhd.jpg";
//FileUtils.copyURLToFile(new URL(url), new File("marvel.jpg"));
String datas =IOUtils.toString(new URL("http://www.163.com"), "gbk");
System.out.println(datas);
}
}
五 文件加锁
public class FileLocking{
public static void main(String[] args)throws Exception{
FileOutputStream fos =new FileOutputStream("file.txt");
FileLock fl =fos.getChannel().tryLock();
if(fl!=null){
System.out.println("Locked File");
TimeUnit.MILLISECONDS.sleep(100);
fl.release();
System.out.println("Release Lock");
}
fos.close();
}
}
//输出结果
Locked File
Released Lock
注意:Socket-Channel、DatagramChannel、ServerSocketChannel不需要加锁。
tryLock()和Lock的区别?
tryLock()是非阻塞式的,如果不能获得锁,它将直接从方法调用处返回。
Lock()是阻塞式的,它要阻塞进程直至锁可以获得,或调用Lock的线程中断,或调用Lock的通道关闭。
tryLock(long position, long size, boolean shared)
Lock(long position, long size, boolean shared) ---第三个参数指定是否是共享锁
加锁的范围
无参的加锁方法对整个文件进行加锁,甚至文件变大后也会如此,但是具有固定尺寸的锁不随文件尺寸的变化而变化(即:如果获得了某一区域上的锁【从position到position+size】,
当文件增大超出position+size时,在position+size之外的部分不会被锁定)
所得类型的判断(独占锁、共享锁)
.isShared()
六、java序列化
6.1 保存(持久化)对象及其状态到内存或者磁盘
但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对 象,并在将来重新读取被保存的对象.
6.2 序列化对象以字节数组保持静态成员不保存
在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装
成对象。必须注意地是,对象序列化保存的是对象的”状态”,即它的成员变量
6.3 序列化用户远程对象传输
6.4 Serializable 实现序列化
只要一个类实现了 java.io.Serializable 接口,那么它就可以被序列化。
6.5 ObjectOutputStream 和 ObjectInputStream 对对象进行序列化及反序列化
通过 ObjectOutputStream 和 ObjectInputStream 对对象进行序列化及反序列化。
6.6 writeObject 和 readObject 自定义序列化策略
在类中增加 writeObject 和 readObject 方法可以实现自定义序列化策略。
6.7 序列化ID
取决于以下三点是否一致:
①类路径
②功能代码
③两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID)
6.8 Transient关键字阻止该变量被序列化到文件中
1、在变量声明前加上 Transient 关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
2、敏感数据在网络中传输
服务器端给客户端发送序列化对象数据(如密码)
只有在客户端进行反序列化时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全。