JAVA基础之流相关

序列化及反序列化

对于一个java对象,若想对其进行网络传输、持久化保存,则该对象必须实现序列化

疑问一: 对于在代码中没有实现序列化的java对象,为什么也能够保存在数据库中,并且能够在网络中传输?

解答一:在Java中,对于没有实现序列化的Java对象,不能直接保存在数据库中或在网络中传输。序列化是一种将对象转换为字节流的过程,它主要用于对象的持久化存储或网络传输。

如果一个Java对象没有实现序列化接口(即实现Serializable接口),则在尝试将其保存到数据库中或在网络中传输时,会抛出NotSerializableException异常。

然而,有一些情况下,即使对象没有实现序列化接口,仍然可以间接地将其保存在数据库中或在网络中传输。这通常是通过其他方式实现的,例如将对象转换为其他格式(如JSON或XML)或者使用特定的ORM框架(对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。如Hibernate)。

ORM框架可以自动将对象转换为关系数据库中的表,并在数据存储和检索过程中处理对象序列化和反序列化。这样,即使对象本身没有实现序列化接口,ORM框架也能够将其保存到数据库中或在网络中传输。

总之,为了直接保存对象到数据库或在网络中传输,Java对象需要实现Serializable接口进行序列化,否则需要借助其他方式或使用ORM框架来实现对象的序列化和反序列化。

文件写入的两个工具

  1. BufferedWriter (带缓冲区的字符流,可以在内存中先暂存一定量的字符,然后再一次性地写入文件,适用于频繁进行文件写入操作的场景)
  2. FileWriter(直接写入文件的字符流,可以将字符直接写入文件,在创建文件写入对象时后面加true可以选择在原文件内容的基础上进行追加
1
2
3
4
5
6
7
8
public static void main(String[] args) {
String content = "需要写入文件的内容";
try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("filePath",true))){
bufferedWriter.write(content);
}catch (Exception e){
//文件写入失败
}
}

文件读取

关于文件的读取,主要通过IO流实现,写入文件用到的类是:FileWriter,写入过程中注意不能在全部写入之前关闭文件流,即在循环写入文件时writer.close();要写在文件的外面。读取文件可以通过Scanner扫描器或者Stream流操作,具体实现入下所示

文件读取demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.huihui.mybatis_demo.utils;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.stream.Stream;

/**
* TODO
*文件的写入和读取
* @author huihui
* @date 2023/7/22 19:40
*/
public class FilesUtil {
public static void main(String[] args) throws IOException {
String fileName = "C:\\Users\\24534\\Desktop\\example.txt";
//writeToFile(fileName);
// 读取文件内容到Stream流中,按行读取
readFromFile1(fileName);
}

private static void readFromFile(String fileName) throws IOException {
Stream<String> lines = Files.lines(Paths.get(fileName));
// 随机行顺序进行数据处理
lines.forEach(ele -> {
System.out.println(ele);
});
}

private static void readFromFile1(String fileName) throws IOException {
try (Scanner sc = new Scanner(new FileReader(fileName))) {
while (sc.hasNextLine()) { //按行读取字符串
String line = sc.nextLine();
System.out.println(line);
}
}

try (Scanner sc = new Scanner(new FileReader(fileName))) {
sc.useDelimiter("\\|"); //分隔符
while (sc.hasNext()) { //按分隔符读取字符串
String str = sc.next();
System.out.println(str);
}
}

//sc.hasNextInt() 、hasNextFloat() 、基础数据类型等等等等。
//文件内容:1|2
try (Scanner sc = new Scanner(new FileReader(fileName))) {
sc.useDelimiter("\\|"); //分隔符
while (sc.hasNextInt()) { //按分隔符读取Int
int intValue = sc.nextInt();
System.out.println(intValue);
}
}

}
private static void writeToFile(String fileName) {
StringBuffer content;
try {
FileWriter writer = new FileWriter(fileName);
for (int i = 1; i<10001;i++){
content = new StringBuffer(i +" soga 浙江省绍兴市"+"\n");
writer.write(content.toString());

}
writer.close();
System.out.println("File written successfully!");
} catch (IOException e) {
System.out.println("An error occurred while writing to the file.");
e.printStackTrace();
}
}

}

文件读取及修改demo

1

Paths.get(inputFileName)的使用

多线程写入文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Override
public void insertRoleInfo(RoleInfoForm roleInfoForm) throws InterruptedException {
//通过多线程并发插入多条记录
//1、创建线程池
int core = 5; //核心线程数
BlockingDeque<Runnable> blockingDeque = new LinkedBlockingDeque<>(5);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(core,core,10, TimeUnit.SECONDS,blockingDeque);

//2、创建countdownlatch
CountDownLatch latch = new CountDownLatch(core);
for(int a=0 ;a<core;a++){
int everyOne = roleInfoForm.getNum()/core;
int index = everyOne*(a+1);
int start = a;
//文件路径
String FILE_NAME = "C:\\Users\\24534\\Desktop\\example1.txt";
threadPoolExecutor.execute(()->{
RoleInfoForm roleInfoForm1 = new RoleInfoForm();
BeanUtils.copyProperties(roleInfoForm,roleInfoForm1);
logger.info(Thread.currentThread().getName()+"线程开始:"+roleInfoForm1.toString());
try{
for(int i = start*everyOne;i<index;i++){
roleInfoForm1.setRoleId(i);
int info =index % 7;
roleInfoForm1.setRoleInfo("你好,这是测试"+info);
roleInfoForm1.setRoleName("sunhui"+info);
// roleInfoMapper.insertRole(roleInfoForm1);//线程中能够调用mapper进行操作
//写入文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_NAME))) {
//TODO 为什么只插入了一行?
writer.write(roleInfoForm1.toString());
writer.newLine();// 添加这一行以正确处理换行符
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (Exception e){
logger.error("插入失败",e);
}finally {
latch.countDown();//
}
});
}
latch.await(5, TimeUnit.SECONDS);
//3、使用完成后关闭线程池
threadPoolExecutor.shutdown();
try {
//
threadPoolExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Stream流

参考连接:Java—Stream流详解_java stream-CSDN博客

1、通过stream流将一个list对象的某个属性转为一个String

1
listObj.stream.map(s->s.getString).collect(Collection(joining("分隔符")));