一、文件操作
(一)文件创建的三种常用方式
package com.yang;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
public class FileCreate {
/**
* 创建文件方式1:指定文件的全路径
*/
@Test
public void fileCreate01(){
File file = new File("e:\\io\\news.txt");
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 创建文件方式2:指定目录下和文件名
*/
@Test
public void fileCreate02(){
File file = new File("e:\\io\\", "news2.txt");
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 创建文件方式3:指定一个File对象(目录)和文件名
*/
@Test
public void fileCreate03(){
File parentFile = new File("e:\\io\\");
File file = new File(parentFile, "news3.txt");
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
(二)File类常用API
package com.yang;
import org.junit.Test;
import java.io.File;
public class FileAPI {
@Test
public void testFileAPI(){
File file = new File("e:\\io\\news.txt");
System.out.println(file.exists()); // 文件是否存在
System.out.println(file.getName()); // 获取文件名
System.out.println(file.getParent()); // 获取文件所在目录
System.out.println(file.getAbsolutePath()); // 获取文件全路径
System.out.println(file.isFile()); // 是否是一个文件
System.out.println(file.isDirectory()); // 是否是一个目录
System.out.println(file.length()); // 文件的大小(字节)
}
}
(三)创建目录和删除目录
package com.yang;
import org.junit.Test;
import java.io.File;
public class Directory {
/**
* 创建一级目录
*/
@Test
public void directoryTest(){
File file = new File("e:\\io\\demo");
// 如果该目录不存在,就创建
if (!file.exists()){
// mkdir方法用来创建一级目录
file.mkdir();
}
}
/**
* 创建多级目录
*/
@Test
public void directoryTest02(){
File file = new File("e:\\io\\a\\b\\c");
// 如果该目录不存在,就创建
if (!file.exists()){
// mkdirs方法用来创建一级目录
file.mkdirs();
}
}
/**
* 删除目录和文件
*/
@Test
public void testDelete(){
File file = new File("e:\\io\\news.txt");
if (file.exists()){
file.delete();
}
}
/**
* 删除目录时,不能直接删除嵌套目录(如果该目录有子目录或子文件,不能直接删除)
*/
@Test
public void testDelete02(){
File file = new File("e:\\io\\a");
if (file.exists()){
file.delete();
}
}
}
二、输入输出流
认识四个抽象类:
- InputStream 字节输入流
- OutputStream 字节输出流
- Reader 字符输入流
- Writer 字符输出流
(一)InputStream
1.FileInputStream
常用API:
int read() // 一次读取一个字节,效率低
int read(byte b[]) // 读取一个字节数组(读取多个字节),效率高
测试:
package com.yang.inputstream_;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;
public class TestFileInputStream {
@Test
public void test(){
FileInputStream fis = null;
int readData = 0;
try {
// 获取FileInputStream对象,用于读取文件的字节输入流对象
fis = new FileInputStream("e:\\io\\demo01.txt");
// read() 将读取到的字节对应的十进制码值(ASCLL码)返回,当该方法返回-1时,说明读取完成
while ((readData = fis.read()) != -1){
System.out.print((char)readData);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test02(){
FileInputStream fis = null;
byte[] data = new byte[8]; // 指定一次最大读取8个字节
int len = 0;
try {
// 获取FileInputStream对象,用于读取文件的字节输入流对象
fis = new FileInputStream("e:\\io\\demo01.txt");
// read(byte b[]) 将实际读取到的字节数量返回,当该方法返回-1时,说明读取完成
while ((len = fis.read(data)) != -1){
System.out.print(new String(data,0,len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2.BufferedInputStream
使用方式和BufferedReader类似,但是该类偏向于操作二进制文件
3.ObjectInputStream
序列化和反序列化:
- 序列化:在保存数据时,保存数据的值和数据类型
- 反序列化:在恢复数据时,恢复数据的值和数据类型
- 如果需要一个类能够实现序列化机制,需要实现两个接口之一
- Serializable
- Externalizable
package com.yang.inputstream_;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class TestObjectInputStream {
@Test
public void test(){
ObjectInputStream ois = null;
try {
// 反序列化时需要注意每个值在序列化时的顺序,反序列化时的顺序和序列化时的顺序要一致
ois = new ObjectInputStream(new FileInputStream("e:\\io\\obj.dat"));
System.out.println(ois.readInt());
System.out.println(ois.readFloat());
System.out.println(ois.readChar());
System.out.println(ois.readUTF());
Object obj = ois.readObject();
System.out.println(obj);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (ois != null){
try {
ois.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
注意:
反序列化时需要注意每个值在序列化时的顺序,反序列化时的顺序和序列化时的顺序要一致
(二)OutputStream
1.FileOutputStream
当向文件中写入数据时,如果该文件不存在,则会自动创建该文件
常用API:
void write(int b) // 写入单个字节
void write(byte b[]) // 写入一个字节数组(多个字节)
void write(byte b[], int off, int len) // 写入一个字节数组的部分数据
测试:
package com.yang.outputstream_;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileOutputStream {
@Test
public void test(){
FileOutputStream fos = null;
try {
// 使用FileOutputStream(String name),默认写入的内容会覆盖原来内容
fos = new FileOutputStream("e:\\io\\output.txt"); // 获取输出流对象
// write(int b) 写入单个字节
fos.write('Y');
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test02(){
FileOutputStream fos = null;
try {
// 只传入一个字符串时,默认写入数据时会覆盖文件原有数据
fos = new FileOutputStream("e:\\io\\output.txt"); // 获取输出流对象
// write(byte b[]) 将一个字节数组写入到文件中
fos.write("hello,world".getBytes()); // getBytes方法将字符串转为字节数组
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test03(){
FileOutputStream fos = null;
try {
// 使用FileOutputStream(String name, boolean append)并设置为true时,默认在文件内容末尾追加
fos = new FileOutputStream("e:\\io\\output.txt",true); // 获取输出流对象
// write(byte b[], int off, int len) 将一个字节数组的部分写入到文件中,从0开始为第一个字符,取len个字符,取不到第len个
fos.write("hello,yang".getBytes(),0,5); // getBytes方法将字符串转为字节数组
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
文件拷贝
package com.yang.outputstream_;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
@Test
public void fileCopy(){
// 创建文件输入输出流
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 边读边写,效率更高
fis = new FileInputStream("d:\\xiazai\\image1.png");
fos = new FileOutputStream("e:\\io\\image1.png");
int dataLen = 0;
byte[] dataArr = new byte[1024];
while((dataLen = fis.read(dataArr)) != -1){
fos.write(dataArr,0,dataLen); // 这里使用write(byte b[], int off, int len)避免拷贝的文件出错
}
System.out.println("拷贝完成...");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (fis != null){
fis.close();
}
if (fos != null){
fos.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2.BufferedOutputStream
使用方式和BufferedWriter类似,但是该类偏向于操作二进制文件
文件拷贝
package com.yang.outputstream_;
import org.junit.Test;
import java.io.*;
public class FIleCopy02 {
@Test
public void test(){
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("e:\\io\\image1.png"));
bos = new BufferedOutputStream(new FileOutputStream("e:\\io\\image2.png"));
byte[] data = new byte[1024];
int readLen;
while((readLen = bis.read(data)) != -1){
bos.write(data,0,readLen);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (bis != null){
bis.close();
}
if (bos != null){
bos.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3.ObjectOutputStream
package com.yang.outputstream_;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestObjectOutputStream {
@Test
public void test(){
ObjectOutputStream oos = null;
try {
// 保存序列化的文件有固定的格式.dat
oos = new ObjectOutputStream(new FileOutputStream("e:\\io\\obj.dat"));
oos.writeInt(1000); // int ==> Integer
oos.writeFloat(1.1f); // float ==> Float
oos.writeChar('Y'); // char ==> Char
// 因为基本数据类型的包装类和String类都直接或间接的实现了Serializable接口,所以可以实现序列化
oos.writeUTF("java");
oos.writeObject(new Dog("大黑",5)); // 序列化对象,需要对应的类实现Serializable接口
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (oos != null){
try {
oos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
class Dog implements Serializable接口,可以实现序列化 { // 该类实现了Serializable接口,可以实现序列化
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
(三)Reader
1.FileReader
常用API:
int read() // 读取单个字符,效率低
int read(char cbuf[]) // 读取一个字符数组
测试:
package com.yang.reader_;
import org.junit.Test;
import java.io.FileReader;
import java.io.IOException;
public class FileReader_ {
@Test
public void test(){
FileReader fr = null;
try {
fr = new FileReader("e:\\io\\reader.txt");
int data = 0;
// read() 读取单个字符,当返回-1时表示读取到文件末尾
while ((data = fr.read()) != -1){
System.out.print((char) data);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fr != null){
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void test02(){
FileReader fr = null;
try {
fr = new FileReader("e:\\io\\reader.txt");
int len = 0;
char[] data = new char[8];
// read(char cbuf[]) 读取一个字符数组,返回的是读取到的字符长度
// 当返回-1时表示读取到文件末尾
while ((len = fr.read(data)) != -1){
System.out.print(new String(data,0,len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fr != null){
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
2.BufferedReader
字符输入流拓展API:
String readLine() // 按行读取文件
测试:
package com.yang.reader_;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TestBufferedReader {
@Test
public void test(){
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("e:\\io\\reader.txt"));
String len;
// readLine 方法按行读取文件,效率更高,当读取到文件末尾时返回null
while ((len = br.readLine()) != null){
System.out.println(len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
3.InputStreamReader
public InputStreamReader(InputStream in, Charset cs) // 该构造器可以指定特定的编码读取文件
测试:
package com.yang.reader_;
import org.junit.Test;
import java.io.*;
public class TestInputStreamReader {
@Test
public void test(){
BufferedReader br = null;
try {
// FileReader 默认使用的是utf-8的编码格式读取文件,当文件编码不是utf-8时,可能出现乱码
br = new BufferedReader(new FileReader("e:\\io\\isr.txt"));
System.out.println(br.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void test02(){
// 使用InputStreamReader指定读取文件时的编码格式
// 使用指定编码读取文件(当指定和文件的编码格式相同时,解决乱码问题)
// 可以将一个字节流转换为一个字符流
BufferedReader br = null;
try {
// InputStreamReader(InputStream in, Charset cs)
br = new BufferedReader(new InputStreamReader(new FileInputStream("e:\\io\\isr.txt"),"gbk"));
System.out.println(br.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
(四)Writer
1.FileWriter
常用API:
void write(int c) // 写入单个字符
void write(char cbuf[]) // 写入一个字符数组(写入多个字符)
void write(char cbuf[], int off, int len) // 写入指定长度的字符数组
void write(String str) // 写入一个字符串
void write(String str, int off, int len) // 从一个字符数组中截取字符并读取到文件中
测试:
package com.yang.writer_;
import org.junit.Test;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter_ {
@Test
public void test(){
FileWriter fw = null;
try {
fw = new FileWriter("e:\\io\\writer.txt");
// write(int c) 写入单个字符
// fw.write('Y');
// fw.write('Y');
// write(char cbuf[]) 写入一个字符数组(写入多个字符)
// String data = new String("hello,world");
// fw.write(data.toCharArray()); // toCharArray方法将一个字符串转为字符数组
// write(String str) 写入一个字符串
fw.write("你好呀!");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (fw != null){
fw.close(); // 或者使用flush(刷新)
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test02(){
FileWriter fw = null;
try {
// FileWriter(String fileName, boolean append) 设置为true时表示为追加
fw = new FileWriter("e:\\io\\writer.txt",true);
// char[] data = {'j','a','v','a','h','e','l','l','o'};
// write(String str, int off, int len) 从一个字符数组中截取字符并读取到文件中
// fw.write(data,4,5);
// write(String str, int off, int len) 从一个字符串中截取字符并读取到文件中
fw.write("hello,world",6,5);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (fw != null){
fw.close(); // 或者使用flush(刷新)
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
2.BufferedWriter
字符输出流拓展API:
void newLine() // 插入一个换行符
测试:
package com.yang.writer_;
import org.junit.Test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class TestBufferedWriter {
@Test
public void test(){
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("e:\\io\\aaa.txt"));
bw.write("hello1");
bw.newLine(); // 插入一个换行符
bw.write("hello2");
bw.newLine();
bw.write("hello3");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
文件拷贝
package com.yang.writer_;
import org.junit.Test;
import java.io.*;
public class FileCopy {
@Test
public void test(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader("e:\\io\\CopyFile.java"));
bw = new BufferedWriter(new FileWriter("e:\\io\\CopyFile02.java"));
String data;
while((data = br.readLine()) != null){ // 按行读取
bw.write(data); // 以字符的形式写入
bw.newLine(); // 换行
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (br != null) {
br.close();
}
if (bw != null){
bw.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3.OutputStreamWriter
public OutputStreamWriter(OutputStream out, String charsetName) // 在写入数据到文件时,指定该文件的编码格式
测试:
package com.yang.writer_;
import org.junit.Test;
import java.io.*;
public class TestOutputStreamWriter {
@Test
public void test(){
// 使用OutputStreamWriter在写入数据到文件时指定编码格式
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(new FileOutputStream("e:\\io\\osw.txt"),"gbk");
osw.write("hello 玉林!!!");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (osw != null){
try {
osw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
三、Properties
- 该类用于读写配置文件
- 有严格的格式:key=value(键值对)
- 键值对不需要空格,值不需要引号标注,默认的类型为String类型
常用API:
void load(InputStream inStream) // 传入一个流对象,用来加载配置文件
String getProperty(String key) // 根据key获取value
Object setProperty(String key, String value) // 如果key存在,则修改value,如果不存在,则设置一个新的key和value
void store(Writer writer, String comments) // 可以以字符流的方式写入数据,comments为生成的注释信息
void store(OutputStream out, String comments) // 可以以字节流的方式写入数据,comments为生成的注释信息
测试:
package com.yang.properties;
import org.junit.Test;
import java.io.*;
import java.util.Properties;
public class TestProperties {
/**
* 使用传统方式读取配置文件
*/
@Test
public void test(){
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("src\\db.properties"));
String data = "";
while((data = br.readLine()) != null) {
String[] dataArr = data.split("=");
System.out.println("key=" + dataArr[0] + " value=" + dataArr[1]);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* 使用Properties类读取配置文件
*/
@Test
public void test02(){
Properties properties = new Properties();
// 加载配置文件
try {
properties.load(new FileReader("src\\db.properties"));
// 输出所有信息到控制台
properties.list(System.out);
// getProperty根据key获取value
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("用户名:" + user);
System.out.println("密码:" + password);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 使用Properties类创建和修改配置文件
*/
@Test
public void test03(){
Properties properties = new Properties();
// setProperty方法,当该键值对不存在时,则添加到配置文件中,如果存在,则修改值
properties.setProperty("charset","utf8"); // 指定字符编码
properties.setProperty("user","张三");
properties.setProperty("password","root");
try {
// 使用字节流的方式保存中文数据到配置文件中时,是中文类型对应的unicode值
// properties.store(new FileOutputStream("src\\db02.properties"),null);
// 第二个参数传入null表示该文件不生成注释信息
properties.store(new FileWriter("src\\db02.properties"),null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}