Java中的文件使用

一、File

代表文件或者目录的类。

2 + File.separator + "a.txt" 
// 2\a.txt

E:\a\b.avi String类型标识这个字符串代表了一个文件

1 + File.separatorChar 
// int + char -> int.所以实际开发中不会经常使用。
//仅仅标记这个字符串是一个file对象,
//而并不会去计算机中真正检查是否有这个文件的存在。
File f = new File("D:\\a.txt");
		
//separator可以自动翻译为当前系统的分隔符(可能不同系统的分隔符是不同的)是一个字符串
//sparatorChar是个字符型,实际用的时候还是separator用的比较多。
File ff = new File("D:" + File.separator + "b.txt");	
//在Windows下,分隔不同的路径用的是; 在Linux中分隔用的是:  
//pathSeparator可以翻译为当前系统分隔不同路径的符号

1.1 重要方法

创建

createNewFile() 当这个文件不存在的时候,才能创建成功
返回的是 要求这个文件的存放目录必须真实存在。
boolean值 只能创建文件,不可以创建目录。

mkdir() 只能创建一层目录。是创建出来文件的。每次只能创建一层目录。

mkdirs() 可以用来一次性创建多层目录

删除

delete() 用于删除文件或者目录,一旦利用代码删除,是从计算中彻底移除,,而不是放到回收站,是不可以撤销的操作。
如果删除的是目录并且这个目录下有子目录或者子文件,则删除失败

获取

getAbsolutePath() 获取file所在的绝对路径

getName() 获取文件名

listFiles() 获取子目录和子文件组成的数组

判断

isAbsolute() 判断是否是一个绝对路径

isFile() 判断是否是一个文件

isDirectory() 判断是否是一个目录‘

exists() 判断文件是否真实存在

canWrite() 判断文件是否可写

isHidden() 判断文件是否是个隐藏文件

获取

listFiles() 获取指定目录下的子文件和子目录组成的文件数组

listFiles(FileFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。

getName() 获取文件名(即使文件不存在,也能够获取文件名)

设置

renameTo(File dest) 表示重新命名或者剪切文件。

//如果路径没有发生改变而只是文件名发生改变,那么就是在 重命名文件
//如果路径发生改变了---剪切
file.renameTo(new File("D:\\file.txt"));     //复制
file.renameTo(new File("D:\\a\\a.txt"));   //剪切

setLastModified(long time) 设置此文件或目录的最后一次修改时间。设置的是毫秒值,从1970年1月1日0时0分0秒开始算起。

file.setLastModified(new SimpleDateFormat("yyyy-MM-dd")
		             .parse("2020-10-10").getTime());

1.2 路径

绝对路径:指以盘符或者/开头的路径。不以当前的路径为基准,而是直接跳转到指定的路径。也就是说绝对路径的计算和当前路径没有任何关系
相对路径:指不以盘符或者/开头的路径。是以当前路径为基准进行计算

.. 表示上一层目录
. 表示本层目录

二、流简介

流动的是数据,用于传输数据的

输入流:指的是数据从外部流向我们的程序。
输出流:指的是数据从程序流向外部。

读取文件----输入流
向文件中写入数据----输出流

根据传输方式分为:输入流和输出流。
根据传输形式分为:字符流和字节流。

输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

这四个基本流都是抽象类。
数据的来源:硬盘、内存、网络、输入设备(Scanner)

字符流带有缓冲区,需要冲刷缓冲区
字节流没有缓冲区,不需要冲刷的操作。

三、FileWriter

继承自Writer的子类OutputStreamWriter

3.1 重要方法

构造方法

FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
如果这个文件不存在,创建该文件
如果这个文件已存在,则创建一个新的文件覆盖原文件。

**FileWriter(File file,boolean append)**根据给定的File 对象构造一个 FileWriter 对象。

普通方法
writer(Stirng str) 写出数据,注意数据并不是直接写到文件中而是写到缓冲区中。如果缓冲区没有满,则数据可能会死在缓冲区中。

flush() 冲刷缓冲区,将数据从缓冲区冲到文件中。

close() 关闭流,流在关闭之前会自动冲刷缓冲区。
注意在关闭之后,流对象依然存在。需要将流对象设置为null来释放对象所占的内存。

//传入文件的路径来构建一个流对象
FileWriter writer = new FileWriter("D:\\a.txt");
writer.write("abc");
//数据不是直接写入文件中,而是写入缓冲区。在缓冲区满了之后才会写到文件中
//如果数据没有填满缓冲区,数据就会死在缓冲区里
//冲刷缓冲区
writer.flush();
//关闭流----释放文件
//流在关闭之前会自动冲刷缓冲区
//流关了,流对象依然存在,只是不能再次使用了。
writer.close();
//为了释放流对象所占用的内存
writer = null;

3.2 流中的异常处理问题

1、流对象要外置定义,内置初始化
2、判断流对象是否初始化成功
3、需要把流对象强制置为null

//流对象需要外置定义,内置初始化
FileWriter writer = null;
try {
	writer = new FileWriter("D:\\a.txt",true);   //在原有内容后面追加
	writer.write("abcdefg");
	writer.flush();    //注意flush()方法放的位置
} catch (IOException e) {
	e.printStackTrace();
}finally{
	//需要判断流对象是否为空,以确定流对象初始化成功
	if(writer != null){
		try {
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			//如果关流失败,强制回收流
			writer = null;
		}	
	}
}

四、FileReader

继承自Writer的子类InputStreamWriter

构造方法
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。

FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。

普通方法
int read() throws IOException 读取单个字符,返回的是该字符的编码

int read(char[] buf,int offset,int length)throws IOException将字符读入数组中的某一部分。如果已到达流的末尾,则返回 -1(常用作while循环的判断条件)
// 准备一个字符数组
char[] cs = new char[10];
fr= new FileReader(“D:\a.txt”);
char[] cs = new char[5];
while((fr.read(cs))!= -1){
System.out.println(new String(cs));
}
如果按上述输出的话,可能会出现最后两个后面部分一样的情况,因为在底层,是采用覆盖的方式的。第一次读取5个字符,第二次再读取的时候,是把第一次的数组拿过来覆盖。如果到了最后一次读的时候,不够5个了,那么后面的元素就没有被覆盖掉,会原样输出。所以一般会用下述的方法:

//定义一个变量来记录本次读取的实际的字符个数
int i = -1;
//读取文件
while ((i = reader.read(cs)) != -1) {
	// 表示从指定数组的指定位置开始转换,转化指定个大小的字符
	System.out.println(new String(cs, 0, i));
}

五、 BufferedReader

它是Reader的直接子类。

构造方法
**BufferedReader(Reader in)**创建一个使用默认大小输入缓冲区的缓冲字符输入流。

BufferedReader(Reader in, int size)创建一个使用指定大小输入缓冲区的缓冲字符输入流。

普通方法:
reader的方法和FileReader类似。多了一个
String readLine() throws IOException 读取一个文本行(也就是我们平常说的一段)。如果已到达流末尾,则返回 null。(常用作while循环的判断条件)
通过下列字符之一即可认为某行已终止:换行 (‘\n’也就是newLine或者nextLine)、回车 (’\r’return) 或回车后直接跟着换行。回车跟换行是有区别的。回车是回到本行的第一个字符处,换行是换到下一行。

BufferedReader br = null;
try {
	br = new BufferedReader(new FileReader("D:\\a.txt"));
	// 定义一个字符串来记录每行的数据
	String line = null;
	// 读取数据
	while ((line = br.readLine()) != null) {
		System.out.println(line);
	}
} catch (Exception e) {
	e.printStackTrace();
} finally {
	/*
	 * 在关闭流的时候,只需要关闭外面流的就可以了
	* 如果非要关闭,那么就要从里向外关闭,否则会有异常
	*/
	if(br != null){
		try {
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			br = null;
		}
	}
}

六、BufferedWriter

它是Reader的直接子类。

构造方法
BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。

BufferedWriter(Writer out, int size) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

普通方法:
newLine() 写入一个行分隔符。实现回车换行的效果,另起一行。

write(char[] cbuf, int off, int len) 写入字符数组的某一部分。

write(int c) 写入单个字符。

write(String s, int off, int len) 写入字符串的某一部分。

注意:Java原生的流不支持Office组件。(Office中会有样式的问题)

七、FileOutputStream/FileInputStream

字节流身上没有缓冲区,不需要冲刷缓冲区的操作。

八、 转换流

InputStreamReader---->字节转字符
OutputStreamWriter—>字符转字节

在转换的时候,可以指定编码:
InputStreamReader(InputStream in,String charsetName)
创建使用指定字符集的 InputStreamReader。

读文件的时候,文件是什么编码,那么构造方法里面接收的编码也应该一致,否则会出现乱码。

OutputStreamWriter(OutputStream out,String charsetName) 创建使用指定字符集的OutputStreamWriter。
只有转化流的构造方法可以指定编码,如果涉及到编码问题就必须用到转化流。

九、 系统流/标准流

系统流本质上都是字节流

System.out 标准输出流
System.in 标准输出流
System.error 标准错误流

正常输出用的是标准输出流(输出的是黑色字体),一旦程序报错输出的是标准错误流(输出的是红色字体)

十、合并流

SequenceInputStream合并流----合并多个流,只有输入没有输出。
需要将多个流这放入一个Vector中,利用Vector对象中的elements方法将Vector转化为一个枚举对象,利用枚举对象产生一个合并流对象

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SquenceInputStreamDemo {
	public static void main(String[] args) throws Exception {
		FileInputStream in1 = new FileInputStream("D:\\a.txt");
		FileInputStream in2 = new FileInputStream("D:\\b.txt");
		FileInputStream in3 = new FileInputStream("D:\\c.txt");
		
		//将流对象放入一个集合中
		Vector<InputStream> vec = new Vector<InputStream>();
		vec.add(in1);
		vec.add(in2);
		vec.add(in3);
		//将集合转化为一个Enumeration对象
		Enumeration<InputStream> e = vec.elements();
		
		//创建合并流对象
		SequenceInputStream sis = new SequenceInputStream(e);
		
		//创建一个输出流
		FileOutputStream out = new FileOutputStream("D:\\d.txt");
		//读取数据
		byte[] bs = new byte[10];
		int i = -1;
		while((i = sis.read(bs))!= -1){
			//写出数据
			out.write(bs,0,i);
		}	
		//关流
		sis.close();
		out.close();	
	}
}

十一、序列化/反序列化

序列化:将对象(注意是对象)的信息完整存储下来的过程(将对象转化为字节流保存起来,并在以后还原这个对象)

持久化(保存到永久存储设备上,比如硬盘)。

反序列化:将对象从存储的地方还原。

注意:
1、一个对象要想被序列化,这个对象对应的类必须实现一个接口Serializable,这个接口中没有任何属性和方法,仅仅用来标识这个类产生的对象可以被序列化。
2、被static/transient修饰的属性没有被序列化出去,(静态属性不属于对象,是属于整个类的)。反序列化回来的时候是对应类型的默认值。
3、一个对象在反序列化的时候,会自动比较比较这个对象的版本号和当前类中的版本号,如果一致才能反序列化回来。
如果一个类中没有手动指定版本号,JVM在运行的时候会根据当前类中的属性和方法自动计算版本号(也就是说一旦类中修改了属性和方法,版本号就会改变)。
如果一个类中手动指定了版本号,修改类的属性和方法,版本号也不会改变。
版本号默认的是private static final long serialVersionUID(修饰符可以改变,但是后面的内容不允许改变)
4、每个文件中只能存储一个序列化的对象
序列化的特点:
当一个对象被序列化的时候,只保存对象的非静态成员变量,不能保存任何的成员方法和静态成员变量。
如果一个对象的成员变量是个对象,那么这个成员变量的对象中的数据也会被保存。
如果一个可序列化的对象包含一个不可序列化的引用,那么整个序列化操作就会失败,可以将该引用用transient修饰。

序列化加密解密
盒子---钥匙-------产生器
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SealedObject;

public class SerialDemo {
	Key key;
	public void serial(Person p) throws Exception{
		//获取一个产生器
		//加密算法(对称加密(有加密有解密)、非对称加密(只有加密没有解密))
		KeyGenerator generator = KeyGenerator.getInstance("DESede");
		
		//由产生器产生钥匙---密钥(miyue)
		 key = generator.generateKey();
		
		//获取锁
		Cipher cipher = Cipher.getInstance("DESede");
		
		//需要将钥匙和锁配对
		cipher.init(Cipher.ENCRYPT_MODE, key);
		
		//需要找一个装对象的盒子
		SealedObject so = new SealedObject(p, cipher);
		
		//序列化出去
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\person.data"));
		out.writeObject(so);
		out.close();
		
	}
	
	public Person deSerail() throws Exception{
		//反序列化
		ObjectInputStream in = new ObjectInputStream(new   FileInputStream("D:\\person.data"));
		SealedObject so = (SealedObject)in.readObject();
		in.close();
		
		return (Person)so.getObject(key);
	}
	
	public static void main(String[] args) throws Exception {
		SerialDemo sd = new SerialDemo();
		Person p = new Person();
		p.setName("是是");
		p.setAge(23);
		sd.serial(p);
		Person pe = sd.deSerail();
		System.out.println(pe.getAge());
		System.out.println(pe.getName());
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值