核心思想#
一切皆文件(Everything is a File),提供了一套统一的接口 (open(), read(), write(), close(), ioctl() 等系统调用) 来操作各种资源,极大地简化了程序设计。
不仅指普通的文本文件、二进制可执行文件、图片、视频等,还包括:
硬件设备: 硬盘 (/dev/sda1)、键盘 (/dev/input)、显示器 (/dev/fb0)、声卡 (/dev/snd)、甚至内存 (/dev/mem) 都被表示为文件。对这些“设备文件”的读写操作实际上是与硬件交互。
进程信息: 正在运行的程序(进程)的信息和控制接口可以通过 /proc 文件系统访问(如 /proc/1234 对应 PID 为 1234 的进程)。
系统信息和配置: /sys 文件系统暴露内核参数、硬件信息和配置选项。
网络套接字: 网络通信的端点。
管道: 进程间通信的通道。
| 特性 | 普通文件 | 管道(Pipe) | Socket(TCP) |
|---|---|---|---|
| 打开方式 | 路径直接打开 | pipe()系统调用 | socket()+bind/connect |
| 数据存储 | 持久化存储 | 内存缓冲区 | 网络传输 |
| 访问模式 | 随机访问 | 顺序访问 | 顺序访问 |
| 生命周期 | 显式创建/删除 | 进程结束自动销毁 | 连接关闭即失效 |
| 进程通信 | 不支持进程间通信 | 支持相关进程通信 | 支持跨网络通信 |
| 阻塞行为 | 通常非阻塞 | 读空阻塞/写满阻塞 | 默认阻塞 |
1. 普通文件#
代码通用实现#
1. python#
- 基本方法:
with open(fp, mode)
示例
</>
python
1with open('text.txt', 'w', encoding='utf-8') as f: # 'w' 覆盖写
2 f.write("Hello Python!\n")
3 f.writelines(["Line 1\n", "Line 2\n"]) # 写入多行
4
5with open('text.txt', 'r', encoding='utf-8') as f:
6 content = f.read() # 一次性读取
7
8with open('text.txt', 'r') as f:
9 lines = f.readlines() # 返回列表
10
11# ========== 二进制文件读写 ==========
12data = b'\x48\x65\x6C\x6C\x6F\x21' # "Hello!" 的二进制
13with open('binary.bin', 'wb') as f: # 'wb' 二进制写
14 f.write(data)
15
16with open('binary.bin', 'rb') as f:
17 binary_content = f.read()
18 print("二进制内容:", binary_content) # b'Hello!'
19 print("解码为字符串:", binary_content.decode('utf-8'))2. c++#
- 基本方法:
fstream- 读:
std::ifstream - 写:
std::ofstream
- 读:
- 注:创建流对象后需要手动关闭
- 示例
</>
c++
1#include <iostream>
2#include <fstream>
3#include <vector>
4#include <string>
5
6int main() {
7 // ========== 文本文件读写 ==========
8 // 写入文本文件
9 std::ofstream textOut("text.txt");
10 if (textOut.is_open()) {
11 textOut << "Hello C++!\n";
12 textOut << "Line 1\nLine 2\n";
13 textOut.close();
14 std::cout << "文本写入成功" << std::endl;
15 } else {
16 std::cerr << "文本文件打开失败" << std::endl;
17 }
18
19 // 读取文本文件
20 std::ifstream textIn("text.txt");
21 if (textIn.is_open()) {
22 std::string line;
23 std::cout << "文本内容:" << std::endl;
24 while (std::getline(textIn, line)) { // 逐行读取
25 std::cout << line << std::endl;
26 }
27 textIn.close();
28 } else {
29 std::cerr << "文本文件打开失败" << std::endl;
30 }
31
32 // ========== 二进制文件读写 ==========
33 // 写入二进制文件
34 std::ofstream binOut("binary.bin", std::ios::binary);
35 char data[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21}; // "Hello!"
36 if (binOut.is_open()) {
37 binOut.write(data, sizeof(data));
38 binOut.close();
39 std::cout << "二进制写入成功" << std::endl;
40 } else {
41 std::cerr << "二进制文件打开失败" << std::endl;
42 }
43
44 // 读取二进制文件
45 std::ifstream binIn("binary.bin", std::ios::binary);
46 if (binIn.is_open()) {
47 // 获取文件大小
48 binIn.seekg(0, std::ios::end);
49 size_t size = binIn.tellg();
50 binIn.seekg(0, std::ios::beg);
51
52 // 读取到vector
53 std::vector<char> buffer(size);
54 binIn.read(buffer.data(), size);
55 binIn.close();
56
57 std::cout << "二进制内容: ";
58 for (char c : buffer) std::cout << c; // 输出 "Hello!"
59 std::cout << std::endl;
60 } else {
61 std::cerr << "二进制文件打开失败" << std::endl;
62 }
63
64 return 0;
65}3. golang#
- 基本方法:
os- 读:
- 整体读取:
os.ReadFile - 逐行读取:
os.Openbufio.NewScanner
- 整体读取:
- 写:
os.WriteFile
- 读:
</>
golang
1package main
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "bufio"
8)
9
10func main() {
11 textContent := "Hello Go!\nLine 1\nLine 2\n"
12 err := os.WriteFile("text.txt", []byte(textContent), 0644) // 覆盖写入
13 if err != nil {
14 fmt.Println("文本写入失败:", err)
15 } else {
16 fmt.Println("文本写入成功")
17 }
18
19 data, err := os.ReadFile("text.txt") // 一次性读取
20 if err != nil {
21 fmt.Println("文本读取失败:", err)
22 } else {
23 fmt.Println("文本内容:\n", string(data))
24 }
25
26 // 逐行读取(使用 bufio)
27 file, err := os.Open("text.txt")
28 if err != nil {
29 fmt.Println("文件打开失败:", err)
30 return
31 }
32 defer file.Close()
33
34 fmt.Println("逐行读取:")
35 scanner := bufio.NewScanner(file)
36 for scanner.Scan() {
37 fmt.Println(scanner.Text()) // 输出每一行
38 }
39
40 // ========== 二进制文件读写 ==========
41 binaryData := []byte{0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21} // "Hello!"
42 err = os.WriteFile("binary.bin", binaryData, 0644)
43 if err != nil {
44 fmt.Println("二进制写入失败:", err)
45 } else {
46 fmt.Println("二进制写入成功")
47 }
48
49 binContent, err := os.ReadFile("binary.bin")
50 if err != nil {
51 fmt.Println("二进制读取失败:", err)
52 } else {
53 fmt.Println("二进制内容:", binContent) // [72 101 108 108 111 33]
54 fmt.Println("解码为字符串:", string(binContent)) // "Hello!"
55 }
56
57 // 大文件分块读取
58 largeFile, err := os.Open("largefile.bin")
59 if err != nil {
60 fmt.Println("大文件打开失败:", err)
61 return
62 }
63 defer largeFile.Close()
64
65 buffer := make([]byte, 1024) // 1KB缓冲区
66 for {
67 n, err := largeFile.Read(buffer)
68 if err == io.EOF {
69 break // 文件结束
70 }
71 if err != nil {
72 fmt.Println("读取错误:", err)
73 break
74 }
75 fmt.Printf("读取 %d 字节\n", n)
76 // 处理 buffer[:n]
77 }
78}2. 管道#
代码实现#
1. python#
</>
python
1import os
2r, w = os.pipe()
3pid = os.fork()
4if pid == 0: # Child
5 os.close(w)
6 data = os.read(r, 100)
7 print("Pipe read:", data.decode())
8 os._exit(0)
9else: # Parent
10 os.close(r)
11 os.write(w, b"Pipe message")
12 os.wait()2. c++#
</>
c++
1#include <iostream>
2#include <fstream>
3#include <unistd.h>
4#include <sys/wait.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
7
8int main() {
9 int fd[2]; pipe(fd);
10 if (fork() == 0) { // Child
11 close(fd[1]);
12 char buf[100];
13 read(fd[0], buf, sizeof(buf));
14 std::cout << "Pipe read: " << buf << std::endl;
15 exit(0);
16 } else { // Parent
17 close(fd[0]);
18 write(fd[1], "Pipe message", 13);
19 wait(nullptr);
20 }
21}3. golang#
</>
golang
1package main
2
3import (
4 "fmt"
5 "io"
6 "net"
7)
8func main() {
9
10 r, w, _ := os.Pipe()
11 go func() {
12 w.Write([]byte("Pipe message"))
13 w.Close()
14 }()
15 pipeData, _ := io.ReadAll(r)
16 fmt.Println("Pipe read:", string(pipeData))
17}3. 网络套接字socket#
代码实现#
1.python#
</>
python
1
2import socket
3# Server
4srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5srv.bind(('127.0.0.1', 12345))
6srv.listen(1)
7# Client
8cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9cli.connect(('127.0.0.1', 12345))
10# Accept and send
11conn, _ = srv.accept()
12conn.send(b"Socket data")
13print("Socket read:", cli.recv(100).decode())
14cli.close(); srv.close()2. c++#
</>
c++
1#include <iostream>
2#include <fstream>
3#include <unistd.h>
4#include <sys/wait.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
7
8int main() {
9 // Server setup
10 int srv_fd = socket(AF_INET, SOCK_STREAM, 0);
11 sockaddr_in addr = {AF_INET, htons(12345), INADDR_ANY};
12 bind(srv_fd, (sockaddr*)&addr, sizeof(addr));
13 listen(srv_fd, 1);
14 // Client connect
15 int cli_fd = socket(AF_INET, SOCK_STREAM, 0);
16 connect(cli_fd, (sockaddr*)&addr, sizeof(addr));
17 // Communication
18 int conn_fd = accept(srv_fd, nullptr, nullptr);
19 send(conn_fd, "Socket data", 12, 0);
20 char buffer[100];
21 recv(cli_fd, buffer, sizeof(buffer), 0);
22 std::cout << "Socket read: " << buffer << std::endl;
23 close(cli_fd); close(srv_fd);
24}3. golang#
</>
golang
1package main
2
3import (
4 "fmt"
5 "io"
6 "net"
7)
8func main() {
9 // Server
10 listener, _ := net.Listen("tcp", "127.0.0.1:12345")
11 go func() {
12 conn, _ := listener.Accept()
13 conn.Write([]byte("Socket data"))
14 conn.Close()
15 }()
16 // Client
17 conn, _ := net.Dial("tcp", "127.0.0.1:12345")
18 sockData, _ := io.ReadAll(conn)
19 fmt.Println("Socket read:", string(sockData))
20}