Java IO 1

Java IO 1

1.传输方式

从数据传输方式或者说是运输方式角度看,可以将 IO 类分为:

  • 字节流
  • 字符流

字节是个计算机看的,字符才是给人看的

1.字节流

(整体结构如下,部分派生类有缺失)

img

2.字符流

img

3.区别

字符 读取文件内容-是从字节流到字符流的桥梁,它将字节流转换为字符流。–字符流用来处理文本文件(可以看做是特殊的二进制文件,使用了某种编码,人可以阅读)。

字节 读取图片 视频文件-主要用于读取二进制数据,比如图片、音频、视频等文件。

简而言之,字节是给计算机看的,字符才是给人看的。

4.字节转换

编码就是把字符转换为字节,而解码是把字节重新组合成字符。

如果编码和解码过程使用不同的编码方式那么就出现了乱码。

从字节流转换到字符流

使用InputStreamReader。它读取字节并将它们解码为字符,通常需要指定字符集来进行正确的解码。

1
2
FileInputStream fis = new FileInputStream("file.txt");//字节流
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");//转换-指定编码

从字符流转换到字节流

使用OutputStreamWriter。它将字符编码为字节并写入到输出流,通常也需要指定字符集。

1
2
3
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file.txt"), "UTF-8");
osw.write("Hello, World!");
osw.close();

2.数据操作

从数据来源或者说是操作对象角度看,IO 类可以分为:

img

1.文件

1.InputStream

image-20241025101621055

文件读取 -字节读取-序列化读取

1
2
FileInputStream fis = new FileInputStream("file.txt");//字节流
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");//转换-指定编码
2.outputstream

image-20241025101726427

1
2
3
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file.txt"), "UTF-8");
osw.write("Hello, World!");
osw.close();
3.writer

image-20241025101855244

Writer类提供了由其子类实现的不同方法。 以下是一些方法: 字符操作

4.reade

image-20241025101930026

5.小节

不带writer和reade的是字节操作-带的是字符操作

2.数组

字节数组(byte[]): ByteArrayInputStream、ByteArrayOutputStream

字符数组(char[]): CharArrayReader、CharArrayWriter


3.管道

PipedInputStream、PipedOutputStream、PipedReader、PipedWriter

4.基本数据类型

DataInputStream、DataOutputStream

5.缓存操作

BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter

6.打印

PrintStream、PrintWriter

7.对象序列化反序列化

ObjectInputStream、ObjectOutputStream

8.转换

inputstreamreader

outputstreamwriter

3.装饰者模式

1.了解装饰者模式

image-20241025103133584

如图-

我们对于机器人两种更新方法功能

1.继承机制

厂商继承第一代研发

2.关联机制-
箱子嵌入以前机器人,我们做研发

85968cca1dec2fb7d5b202dc33c9c613

类图

49f394cb8ed5bef0b96b4ace390be858

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


interface Robota
{
void sayHello();
}
class RobotImpl implements Robota
{
@Override
public void sayHello() {
System.out.println("唱歌跳舞");
}
}
abstract class Tirtest implements Robota {
private Robota robot;

public Tirtest(Robota robot) {
this.robot = robot;
}

@Override
public void sayHello() {
robot.sayHello();
}
public void saypp()
{
robot.sayHello();
System.out.println("pp");
}

}
class test extends Tirtest{

public test(Robota robot) {
super(robot);
}
}

public class decorator {
public static void main(String[] args) {
Robota robot = new RobotImpl();
test t = new test(robot);
t.saypp();
}


}






装饰器模式是在原有类的基础上动态添加新的功能,这种添加功能的方式不同于继承,它是在对象层面实现功能扩展,而不是继承的类层面,因此说装饰器模式比继承更加灵活。另外,装饰器模式属于结构型设计模式。之前讲的都是创建型设计模式。创建型可以理解为生成新的对象,而结构型可以理解为构建更大的类或类对象。

2.解读inputStream

InputStream 是抽象组件;

FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作;

FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能。例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。


image

实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。

1
FileInputStream fileInputStream =newFileInputStream(filePath);BufferedInputStream bufferedInputStream =newBufferedInputStream(fileInputStream);

DataInputStream 装饰者提供了对更多数据类型进行输入的操作,比如 int、double 等基本类型。

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


interface inputStreama
{
void sayHello();
}
class FileInputStreama implements inputStreama
{
@Override
public void sayHello() {
System.out.println("文件操作");
}

}
abstract class FilterInputStreamq implements inputStreama {
private inputStreama robot;

public FilterInputStreamq(inputStreama robot) {
this.robot = robot;
}

@Override
public void sayHello() {
robot.sayHello();
}
public void saypp()
{
robot.sayHello();
System.out.println("文件传输增强");
}

}
class test extends FilterInputStreamq {

public test(inputStreama robot) {
super(robot);
}
}

public class decorator {
public static void main(String[] args) {
inputStreama robot = new FileInputStreama();
test t = new test(robot);
t.saypp();
}

}

4.常见类的使用

本文主要介绍Java IO常见类的使用,包括:磁盘操作,字节操作,字符操作,对象操作和网络操作。

image-20241104140007947

IO常见类

file相关

File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。

递归地列出一个目录下所有文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void listAllFiles(File dir) {
if (dir == null || !dir.exists()) {
return;
}
if (dir.isFile()) {
System.out.println(dir.getName());
return;
}
for (File file : dir.listFiles()) {
listAllFiles(file);
}
}


字节流相关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void copyFile(String src, String dist) throws IOException {

FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dist);
byte[] buffer = new byte[20 * 1024];

// read() 最多读取 buffer.length 个字节
// 返回的是实际读取的个数
// 返回 -1 的时候表示读到 eof,即文件尾
while (in.read(buffer, 0, buffer.length) != -1) {
out.write(buffer);
}

in.close();
out.close();
}

实现逐行输出文本文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void readFileContent(String filePath) throws IOException {

FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);

String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}

// 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
// 在调用 BufferedReader 的 close() 方法时会去调用 Reader 的 close() 方法
// 因此只要一个 close() 调用即可
bufferedReader.close();
}

序列化 Serializable & transient

序列化就是将一个对象转换成字节序列,方便存储和传输。

  • 序列化: ObjectOutputStream.writeObject()
  • 反序列化: ObjectInputStream.readObject()

不会对静态变量进行序列化,因为序列化只是保存对象的状态,静态变量属于类的状态。

Serializable

序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。


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
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化编码
A a1 = new A(123, "abc");
String objectFile = "file/a1";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile));
objectOutputStream.writeObject(a1);
objectOutputStream.close();
//序序列化解码
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(objectFile));
A a2 = (A) objectInputStream.readObject();
objectInputStream.close();
System.out.println(a2);
}

private static class A implements Serializable {
private int x;
private String y;

A(int x, String y) {
this.x = x;
this.y = y;
}

@Override
public String toString() {
return "x = " + x + " " + "y = " + y;
}
}

transient

transient 关键字可以使一些属性不会被序列化。

ArrayList 中存储数据的数组 elementData 是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。


1
2
private transient Object[] elementData;

java网络支持

image-20241104140528036

inetAdress

没有公有的构造函数,只能通过静态方法来创建实例。

1
2
InetAddress.getByName(String host);
InetAddress.getByAddress(byte[] address);
url

可以直接从 URL 中读取字节流数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) throws IOException {

URL url = new URL("http://www.baidu.com");

/* 字节流 */
InputStream is = url.openStream();

/* 字符流 */
InputStreamReader isr = new InputStreamReader(is, "utf-8");

/* 提供缓存功能 */
BufferedReader br = new BufferedReader(isr);

String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}

br.close();
}

sockets
  • ServerSocket: 服务器端类
  • Socket: 客户端类
  • 服务器和客户端通过 InputStream 和 OutputStream 进行输入输出。

image

datagram
  • DatagramSocket: 通信类
  • DatagramPacket: 数据包类

Java IO 1
http://example.com/2024/10/25/java/javaIo/javaIo1/
作者
John Doe
发布于
2024年10月25日
许可协议