文件
文件是保存数据的地方
- 文件流
文件在程序中是以流的形式来操作
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流: 数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
常用文件操作
-
创建文件对象的相关构造器和方法
new File(String pathname) //根据路径构建一个File对象
new File(File parent,String child)//根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建public class CreateNewFile { public static void main(String[] args) throws IOException { File file = new File("D:\\个人数据\\text.txt"); File fileP = new File("D:\\个人数据"); File file1 = new File(fileP,"\\text.txt"); File file2 = new File("D:\\个人数据","\\text.txt"); //创建文件方法: createNewFile() if (file.createNewFile()){ System.out.println("文件创建成功"); if (file.delete()){ System.out.println("文件删除成功"); } } }
构造File对象时,既可以传入绝对路径,也可以传入相对路径。绝对路径是以根目录开头的完整路径,如:
// 假设当前目录是C:\Docs
File f1 = new File("sub\\javac"); // 绝对路径是C:\Docs\sub\javac
//可以用.表示当前目录,..表示上级目录
File f3 = new File(".\\sub\\javac"); // 绝对路径是C:\Docs\sub\javac
File f3 = new File("..\\sub\\javac"); // 绝对路径是C:\sub\javac
-
获取文件信息
//先创建文件对象 File file = new File("e:\\news1.txt"); //调用相应的方法,得到对应信息 System.out.println("文件名字= "+ file.getName()); System.out.println("文件绝对路径="+ file.getAbsolutePath()); System.out.println("文件父级目录=" + file.getParent()); System.out.println("文件大小(字节)=" + file.Length()); System.out.println("文件是否存在=" + file.exists());//T System.out.println("是不是一个文件=" + file.isFile());//T System.out.println("是不是一个目录=" + file.isDirectory());//F
-
文件目录操作
mkdir创建一级目录、mkdirs创建多级目录、delete删除空目录或文件File file = new File("e:\\demo"); File file2 = new File("e:\\demo\\a\\b"); file.mkdir();//创建一级目录 file2.mkdirs();//创建多级目录 file.delete();
IO流原理及 流的分类
-
l/O是Input/Output的缩写l/O技术是非常实用的技术,用于处理数据传输如读/写文件,网络通讯等。
-
Java程序中,对于数据的输入/输出操作以”流(stream)” 的方式进行; java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
-
流的分类
按操作数据单位不同分为: 字节流(8 bit) 二进制文件,字符流(按字符)文本文件
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流/包装流
文件字节流
-
InputStream/OutputStream
OutputStream提供了一个flush()方法,它的目的是将缓冲区的内容真正输出到目的地。向磁盘、网络写入数据的时候,出于效率的考虑,操作系统并不是输出一个字节就立刻写入到文件或者发送到网络,而是把输出的字节先放到内存的一个缓冲区里(本质上就是一个byte[]数组),等到缓冲区写满了,再一次性写入文件或者网络。对于很多IO设备来说,一次写一个字节和一次写1000个字节,花费的时间几乎是完全一样的,所以OutputStream有个flush()方法,能强制把缓冲区内容输出。
FileInputStream/FileOutputStream
public static void main(String[] args) throws IOException {
String filePath = "d:\\xxx.txt";
//new FileOutputStream(filePath) 写入方式 会覆盖文件之前内容,如果文件不存在,FileOutputStream会创建文件
//FileOutputStream fileOutputStream = new FileOutputStream(filePath);
//new FileOutputStream(filePath,true) 写入方式 不会覆盖文件之前内容,追加到文件末尾
FileOutputStream fileOutputStream = new FileOutputStream(filePath,true);
String str = "wow";
fileOutputStream.write(str.getBytes());
int readDate;
FileInputStream fileInputStream = new FileInputStream(filePath);
//读取文件
//fileInputStream.read()方法从该输入流读取一个字节的(ASCII)数据。如果没有输入可用,此方法将阻止。如果返回-1 ,表示读取完毕
while ((readDate = fileInputStream.read()) != -1){
System.out.print((char) readDate);
}
//释放资源
fileInputStream.close();
fileOutputStream.close();
}
文件拷贝
//文件拷贝
//读取文件--指定位置写入文件
String path = "D:\\wow.txt";//原目录
String desPath = "D:\\demo\\wow.txt";//目标目录
FileInputStream fileInputStream = new FileInputStream(path);
FileOutputStream fileOutputStream = new FileOutputStream(desPath);
byte[] bytes = new byte[1024];
int bytesLen = 0;
//读取文件数据
while ((bytesLen = fileInputStream.read(bytes)) !=-1){
//写入文件数据
fileOutputStream.write(bytes,0,bytesLen);
}
//关闭资源
fileInputStream.close();
fileOutputStream.close();
文件字符流FileReader/FileWriter
-
FileReader相关方法
- new FileReader(File/String)
- read:每次读取单个字符,返回该字符,如果到文件未尾返回-1
- read(char): 批量读取多个字符到数组,返回读取到的字符数,如果到文件未尾返回-1
相关API: - new String(char[):将char[]转换成String
- new String(char[l],off;len):将charl]的指定部分转换成String
-
FileWriter
1)new FileWriter(File/String): 覆盖模式,相当于流的指针在首端
2)new FileWriter(File/String,true): 追加模式,相当于流的指针在尾端
3)write(int):写入单个字符
4)write(charl]):写入指定数组
5)write(charll,off,len):写入指定数组的指定部分
6)write (string):写入整个字符串
7)write(string,offlen):写入字符串的指定部分
相关API: String类: toCharArray:将String转换成char[]
注意:
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!//文件字符流操作 String path = "d:\\wow.txt"; FileReader fileReader = new FileReader(path); FileWriter fileWriter = new FileWriter(path); //写入 fileWriter.write("哈哈我哈"); fileWriter.flush(); //单个字符读取 /*int data; while ((data = fileReader.read()) != -1){ System.out.println((char) data); }*/ //多个字符读取 char[] chars = new char[2]; int dataLen; while ((dataLen = fileReader.read(chars)) != -1){ System.out.println(new String(chars,0,dataLen)); } fileReader.close(); fileWriter.close();
节点流和处理流
1.节点流可以从一个特定的数据源读写数据 ,如FileReader、FileWriter
2.处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流之上,为程序提供
更为强大的读写功能,如BufferedReader、BufferedWriter
BufferedReader一般读取文本文件
String filePath = "D:\\wow.txt";
/*演示BufferedReader*/
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
//bufferedReader.readLine();//按行读取文件,当返回null时,表示读取完毕
String line;
while ((line=bufferedReader.readLine()) != null) {
System.out.println(line);
}
//关闭流
bufferedReader.close();
演示BufferedWriter
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello");
bufferedWriter.newLine();//换行
bufferedWriter.write("hello2");
bufferedWriter.write("hello3");
bufferedWriter.close();
BufferedInputStream、BufferedOutputStream(字节)
/*演示BufferedInputStream、BufferedOutputStream*/
String srcFiletPath = "C:\\Users\\x'l'f\\Pictures\\Saved Pictures\\壁纸库\\child_river_dreams.jpg";
String desFiletPath = "D:\\xxx.jpg";
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFiletPath));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFiletPath));
byte[] bytes = new byte[1024];
int readLen = 0;
while ((readLen = bufferedInputStream.read(bytes)) != -1){
bufferedOutputStream.write(bytes,0,readLen);
}
bufferedInputStream.close();
bufferedOutputStream.close();
ObjectInputStream、ObjectOutputStream(对象流,提供序列化和反序列化)
- 序列化和反序列化
序列化:就是在保存数据时,保存数据的值和数据类型;
反序列化:就是在恢复数据时,恢复数据的值和数据类型;
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:Serializable // 这是一个标记接口
Externalizable
public static void main(String[] args) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据保存到文件
objectOutputStream.write(100);
objectOutputStream.writeBoolean(true);
objectOutputStream.writeUTF("哈哈哈哈");
//保存对象
objectOutputStream.writeObject(new Dog("旺旺",3));
//反序列化-读取顺序和写入一致,不一致会报错
System.out.println(objectInputStream.read());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readUTF());
System.out.println(objectInputStream.readObject().toString());
objectOutputStream.close();
objectInputStream.close();
}
//实现Serializable接口,标记该类可序列化
class Dog implements Serializable{...}
注意事项和细节说明
1)读写顺序要一致。
2)要求实现序列化或反序列化对象 ,需要实现 Serializable。
3)序列化的类中建议添加SerialVersionUID.为了提高版本的兼容性。
private static final long serialVersionUID = 1L;
4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员。
5)序列化对象时,要求里面属性的类型也需要实现序列化接口。
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。
System.in 、System.out(标准输入输出流)
-
System.in 标准输入流:编译类型是InputStream,运行类型是BufferedInputStream,标准输入设备是键盘
-
OutputStream 标准输出流:编译类型是PrintStream,运行类型也是PrintStream,标准输出设备是显示器
InPutStreamReader、OutputStreamWriter(转换流)可以处理因数据编码不同时产生乱码问题
-
InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流);
-
OutputStreamWriter:Writer的子类,实现将OutputStream(字节流包装成Writer(字符流);
-
当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流;
-
可以在使用时指定编码格式(比如 utf-8,gbk,gb2312,ISO8859-1 等)
//字节流、字符流转换 //1.FileInputStream转换为InputStreamReader(字节流-->转换流) InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"UTF-8");//UTF-8传入不同charset //2.InputStreamReader传入BufferedReader(转换流-->字符流) BufferedReader br = new BufferedReader(isr); System.out.println(br.readLine()); br.close();
PrintStream、PrintWiter(打印流)
- 打印只有输出流,没有输入流
//字节打印流PrintStream,默认情况下输出数据的位置是标准输出(显示器),可以进行修改
PrintStream out = System.out;
out.println("QAQ");
//print底层是write,所以可以直接调用write进行打印/输出
out.write("0.o".getBytes());
out.close();
//修改打印输出位置到文件filePath位置
System.setOut(new PrintStream(filePath));
System.out.println("o.0,0.o");//此时将输出到文件
//字符打印流PrintWrite
PrintWriter pr = new PrintWriter(System.out);//输出到屏幕
PrintWriter pr2 = new PrintWriter(new FileWriter(filePath));//输出到文件
pr.close();
pr2.close();
配置文件properties类
-
专门用于读写配置文件的集合类
-
配置文件的格式是键值对( 键=值),键值对不需要有空格,值不需要引号。默认类型是String
Properties的常见方法
load: 加载配置文件的键值对到Properties对象
list:将数据显示到指定设备
getProperty(key):根据键获取值
setProperty(key;value):设置键值对到Properties对象
store:将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码
//创建Properties对象
Properties ppt = new Properties();
//加载配置文件
ppt.load(new FileReader("src\\main\\resources\\test.properties"));
//显示
ppt.list(System.out);
//写入数据到properties文件
//创建 k-v,如果k存在则是修改值
ppt.setProperty("user","Tom");
ppt.setProperty("user2","舟山");
//保存数据,如果文件存在就是修改,不存在会创建新文件写入,comments内容为注释
ppt.store(Files.newOutputStream(Paths.get("src\\main\\resources\\test.properties")),null);
System.out.println("保存配置成功");