import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import java.io.*;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;
/**
* @author binfirechen
* @version 1.0
* @date 2022/8/9 22:51
*/
public class FileIOTest {
/**
* 文件:文件名,大小,路径,最后修改时间等
*
* @throws IOException
*/
@Test
void testFileInfo() throws IOException {
ClassPathResource resource = new ClassPathResource("1.png");
String path = resource.getFile().getPath();
System.out.println(path);
File file = new File(path);
if (!file.exists()) {
throw new FileNotFoundException();
}
System.out.println("文件名:" + file.getName());
System.out.println("文件路径:" + file.getPath());
System.out.println("文件绝对路径:" + file.getAbsolutePath());
System.out.println("文件大小:" + file.length());
long l = file.lastModified();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(l);
System.out.println("文件最后修改时间:" + format);
System.out.println("是否是文件:" + file.isFile());
//File.separator 不同操作系统对应的分割符
File file1 = new File("D:" + File.separator + "history");
System.out.println("文件路径:" + file1.getAbsolutePath());
System.out.println("是否是文件:" + file1.isFile());
ClassPathResource resourceFile = new ClassPathResource("1.txt");
String filePath = resource.getFile().getPath();
File file2 = new File(filePath);
String newFilePath = filePath.replace("1.txt", "2.txt");
File file3 = new File(newFilePath);
file2.renameTo(file3);
}
void PrintFiles(File fileDir, String sepecator) {
if (fileDir.isFile())
return;
System.out.println(sepecator + "+" + fileDir.getName());
File[] files = fileDir.listFiles();
for (File file : files) {
if (file.isFile()) {
System.out.println(" " + sepecator + "-" + fileDir.getName());
} else {
PrintFiles(file, " ");
}
}
}
/**
* 字符 (编码表) 码值
* 编码:把看的懂的字符到编码表中找到对应的码值
* 解码:把码值到编码表中找到看的懂的字符
* <p>
* ASIII:美国人
* ISO8859-1:欧洲人
* GB2312:中国汉字,英文占1个字节,中文占2个字节
* GBK:中国汉字,加少数名族文字
* Unicode:国际编码表,所有文字都用2个字节,只代表一个规范,但是默认会加上-2,-1作为前缀
* UTF-8:最多用3个字节表示,英文占1个字节,中文占3个字节
* UTF-16:不管中英文都占用两个字节 ,unicode默认会采用utf-16 作为编码
* 日常接触最多的是
* iso8859-1 gbk utf-8
*
* @throws UnsupportedEncodingException
*/
private String a = "a中国";
/**
* GBK,英文默认1个字符,中文占2个字符
*/
@Test
public void testGBK() {
try {
//java默认采用GBK编码,英文占用1个字节,中文占用2个字节
byte[] bytes = a.getBytes(); //采用GBK编码
System.out.println(java.util.Arrays.toString(bytes)); //[97, -42, -48, -71, -6]
System.out.println(new String(bytes)); //a中国
System.out.println(new String(bytes, 1, 2, "GBK")); //中
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Test
public void testUtf8() {
try {
//utf-8编码,英文占用1个字节,中文占用3个字节
byte[] bytes = a.getBytes("utf-8"); //采用GBK编码
System.out.println(java.util.Arrays.toString(bytes)); //[97, -28, -72, -83, -27, -101, -67]
System.out.println(new String(bytes, "utf-8"));
System.out.println(new String(bytes, 1, 3, "utf-8")); //中
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Test
public void testUtf16() {
try {
//unicode只是一种规范,内部实际上时utf-16的实现,不管中英文都占用2个字节,前面加上-2,-1作为一个标记
byte[] bytes = a.getBytes("unicode");
System.out.println(java.util.Arrays.toString(bytes)); //[-2, -1, 0, 97, 78, 45, 86, -3]
bytes = a.getBytes("utf-16");
System.out.println(Arrays.toString(bytes)); //[-2, -1, 0, 97, 78, 45, 86, -3]
System.out.println(new String(bytes, "utf-16"));
System.out.println(new String(bytes, 2, 2, "unicode")); //a
System.out.println(new String(bytes, 4, 2, "unicode")); //中
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Java中默认采用GBK编码
*/
@Test
public void getDefaultCharaset() {
Charset charset = Charset.defaultCharset();
System.out.println("default Charset:" + charset.name());
}
@Test
public void test边读边写() throws IOException {
InputStream inputStream = new FileInputStream("./files/1.png");
OutputStream outputStream = new FileOutputStream("./files/2.png");
byte[] buffer = new byte[1024];
int count = 0;
while ((count = inputStream.read(buffer, 0, buffer.length)) != -1) {
outputStream.write(buffer, 0, count);
}
outputStream.close();
inputStream.close();
System.out.println("write success.");
}
/**
* 缓冲输入输出字符流
* ---------------------------------------------
* BufferedReader 增强了FileReader.ReaderLine()功能
* BufferedWriter
* bufferWriter.newLine();
* bufferWriter.write("abc");
*
* @throws IOException
*/
@Test
void txtRead() throws IOException {
Reader reader = new FileReader("./files/2.txt");
BufferedReader bufferReader = new BufferedReader(reader);
String content = null;
while ((content = bufferReader.readLine()) != null) {
System.out.println(content);
}
bufferReader.close();
Writer writer = new FileWriter("./files/2.txt", true);
BufferedWriter bufferWriter = new BufferedWriter(writer);
bufferWriter.newLine();
bufferWriter.write("abc");
bufferWriter.newLine();
bufferWriter.write("abc");
bufferWriter.newLine();
bufferWriter.write("abc");
bufferWriter.close();
}
/**
* 字节流
* ------------------------------------------
* InputStream 所有输入字节流的基类
* --FileInputStream 读取文件数据的输入字节流
* --BufferedInputStream 缓冲输入字节流,内部维护者一个8kb的字节数组
* --SequenceInputStream 应用于一次读取多个文件
* OutputStream
* --FileOutputStream
* --BufferedOutputStream
* <p>
* <p>
* <p>
* 字符流 =字节流+编码(解码)
* -------------------------------------
* Reader 所有输入字符流的基类
* --FileReader
* --BufferedReader +readLine();
* Writer
* --FileWriter
* --BufferdWriter +newLine();
*
* @throws IOException
*/
@Test
void testFileSplitMerge() throws IOException {
ArrayList<String> list = new ArrayList<>();
FileInputStream inStream = new FileInputStream("1.wmv");
byte[] buffer = new byte[1024 * 1024]; //1M一个文件
int cnt = 0;
int index = 1;
while ((cnt = inStream.read(buffer)) != -1) {
String fileName = "./files/" + (index++) + ".data";
list.add(fileName);
OutputStream optStream = new FileOutputStream(fileName);
optStream.write(buffer, 0, cnt);
optStream.close();
}
inStream.close();
System.out.println("切割完成.");
//合并
Vector<InputStream> vector = new Vector<InputStream>();
for (String fileName : list) {
vector.add(new FileInputStream(fileName));
}
if (vector.isEmpty()) {
return;
}
Enumeration<InputStream> elements = vector.elements();
InputStream sequenceInputStream = new SequenceInputStream(elements);
OutputStream optStream = new FileOutputStream("./files/merge.wmv");
buffer = new byte[1024 * 1024];
cnt = 0;
while ((cnt = sequenceInputStream.read(buffer)) != -1) {
optStream.write(buffer, 0, cnt);
}
optStream.close();
sequenceInputStream.close();
//删除拆分的文件
for (String fileName : list) {
File file = new File(fileName);
file.delete();
}
System.out.println("合并完成");
}
/**
* ObjectOutputStream writeObject
* ObjectInputStream readObject
* <p>
* 1.Object类必须要实现Serializable接口
* 2.当类需要变化的时候,也能正常被发序列化,那么加上默认的serialVersionUID
* 3.当个别字段不想被序列化到文件中,那么使用 transient修饰
* 4.如果类中引用了其他引用对象,那么其余引用对象也必须要实现Serializable接口,该对象才能被序列化
*/
@Test
void testSerialize() throws IOException, ClassNotFoundException {
Address p = new Address("111", "222");
OutputStream outStream=new FileOutputStream("./files/person");
ObjectOutputStream objOutStream=new ObjectOutputStream(outStream);
objOutStream.writeObject(p);
System.out.println("序列化成功");
InputStream inStream=new FileInputStream("./files/person");
ObjectInputStream objInStream=new ObjectInputStream(inStream);
p=(Address)objInStream.readObject();
System.out.println("反序列化成功");
System.out.println(p);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
class Address implements Serializable {
private static final long serialVersionUID = 1L;
private String country;
private String city;
@Override
public String toString() {
return "Address{" +
"country='" + country + '\'' +
", city='" + city + '\'' +
'}';
}
}