跳过正文
  1. Teches/
  2. 通用编程思想/
  3. 项目基础功能/

Linux文件读写

·1080 字·6 分钟
目录

核心思想
#

一切皆文件(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
#

  1. 基本方法: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++
#

  1. 基本方法:fstream
    1. 读:std::ifstream
    2. 写:std::ofstream
  2. 注:创建流对象后需要手动关闭
  3. 示例
</> 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
#

  1. 基本方法:os
    1. 读:
      1. 整体读取:os.ReadFile
      2. 逐行读取:
        1. os.Open
        2. bufio.NewScanner
    2. 写: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}