IO和网络库支持程序访问文件和网络,包括标准输入输出IO、文件IO、网络IO

C语言

C语言的文件IO位于#include <stdio.h>库,主要包含如下几个函数

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
// 打开文件
FILE *fopen(const char *filename, const char *mode);
// mode
// "r":以只读方式打开文件,文件必须存在。
// "w":以只写方式打开文件,如果文件已存在,会清空文件内容;如果文件不存在,会创建新文件。
// "a":以追加模式打开文件,数据写入到文件末尾,文件不存在时会创建。
// "r+":以读写模式打开文件,文件必须存在。
// "w+":以读写模式打开文件,文件不存在时会创建,已存在时会清空文件内容。
// "a+":以读写模式打开文件,数据写入文件末尾,文件不存在时会创建。

// 关闭文件
int fclose(FILE *stream);

// 读取文件
// 从文件中读取一个字符。
int fgetc(FILE *stream)
// 从文件中读取一行,最多读取 num-1 个字符。
int fgets(char *str, int num, FILE *stream)
// 从文件中读取多个ptr对象(如结构体、数组等),每个对象大小为 size,读取 count 个对象。
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
int numbers[5];
size_t n = fread(numbers, sizeof(int), 5, file);

// 写入文件
// 将字符 c 写入文件
int fputc(int c, FILE *stream)
// 将字符串 str 写入文件,自动加上字符串的结束符 \0
int fputs(const char *str, FILE *stream)
// 写入多个对象到文件,每个对象大小为 size,写入 count 个对象。
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
int numbers[5] = {1, 2, 3, 4, 5};
size_t n = fwrite(numbers, sizeof(int), 5, file);

// 文件定位
// 设置文件指针的位置。offset 是偏移量,whence 是参考位置。
// SEEK_SET:从文件开头开始偏移。
// SEEK_CUR:从当前位置开始偏移
// SEEK_END:从文件末尾开始偏移
fseek(FILE *stream, long offset, int whence):
// 获取当前文件指针的位置
ftell(FILE *stream)

// 检查文件是否已读到末尾
int feof(FILE *stream);

// 标准输入输出
// %d:输出10进制整数; %f:输出浮点数; %s:输出字符串; %c:输出字符;%x:输出十六进制整数。
int printf(const char *format, ...);
int scanf(const char *format, ...);
scanf("%d", &a);
// 从标准输入读取一个字符。
getchar()
// 将一个字符输出到标准输出
putchar()

// 从文件中按指定的格式读取数据,并将读取的数据存储到变量。
int fscanf(FILE *stream, const char *format, ...);
// fprintf() 向文件中写入格式化的数据
int fprintf(FILE *stream, const char *format, ...);

// sprintf() 将格式化的数据写入字符串。
int sprintf(char *str, const char *format, ...);
sprintf(buffer, "Number: %d, Pi: %.2f", num, pi);

// sscanf() 函数用于从字符串中按指定格式读取数据
int sscanf(const char *str, const char *format, ...);

C语言网络socket 直接使用linux相关系统调用

服务端,绑定(bind)到指定端口。监听(listen)端口,等待客户端连接。接受(accept)客户端的连接请求。进行数据通信(send,recv, read, write),关闭 Socket(close)。

客户端,创建 Socket。连接(connect)到服务器端。发送和接收数据。关闭 Socket。

涉及到的系统调用

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
// 创建socket
// domain:指定协议族,常用的有:
// AF_INET:IPv4协议。
// AF_INET6:IPv6协议。
// AF_UNIX:Unix 域协议,用于同一机器上的进程间通信。
//
// type:指定套接字类型,常见的有:
// SOCK_STREAM:面向连接的流式套接字,通常用于 TCP。
// SOCK_DGRAM:数据报套接字,通常用于 UDP。
//
// protocol:指定协议,通常为 0,表示由操作系统自动选择合适的协议。
int socket(int domain, int type, int protocol);

// bind() 用于将套接字与本地IP 地址和端口号绑定。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到任意IP地址
server_addr.sin_port = htons(PORT); // 设置端口号
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}

// backlog:等待连接队列的最大长度,表示操作系统在拒绝新连接之前,最多允许排队的连接请求数。
int listen(int sockfd, int backlog);

// accept() 用于接受一个传入的连接请求。该函数会阻塞,直到有客户端连接。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

// connect() 用于客户端请求与服务器建立连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

// 从socket fd获得数据
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t read(int fd, void *buf, size_t count);
// 向socket fd发送数据
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t write(int fd, const void *buf, size_t count);

// 关闭一个打开的套接字
int close(int fd);
// shutdown() 可用于关闭连接的一部分(如读或写)
// how:关闭方式,可能的值有:SHUT_RD:关闭读取。SHUT_WR:关闭写入。SHUT_RDWR:关闭读取和写入。
int shutdown(int sockfd, int how);

C++

C++ 没有提供网络库,只提供文件IO库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ifstream:用于从文件中读取数据。
// ofstream:用于向文件中写入数据。
// fstream:用于从文件中读取和向文件中写入数据

// 可用文件流类的构造函数或者 open() 方法来打开文件。mode可以选择
// ios::in:以读取模式打开文件(默认)。
// ios::out:以写入模式打开文件。
// ios::app:以追加模式打开文件(写入内容会被追加到文件末尾)。
// ios::binary:以二进制模式打开文件。
// ios::trunc:如果文件已经存在,截断文件为零长度
std::ofstream outfile("example.txt", std::ios::out | std::ios::trunc);

// 检查文件流状态
is_open() // 检查文件是否成功打开。
eof() // 检查是否已经到达文件末尾。

// 文件指针定位
seekg(offset, direction) // 设置读取位置。
seekp(offset, direction) // 设置写入位置。
tellg() // 返回当前读取位置。
tellp() // 返回当前写入位置

// cout 是 C++ 标准输出流对象,是一个 ostream 类型的对象
// C++标准输入输出很反人类,建议直接用C库

按行读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
#include <string>

int main() {
std::ifstream infile("example.txt");

if (!infile) {
std::cerr << "Failed to open file.\n";
return 1;
}

std::string line;
while (std::getline(infile, line)) {
std::cout << line << std::endl;
}

infile.close();
return 0;
}

JAVA

文件IO

JAVA文件流分为两种主要类型:字节流和字符流。字节流用于处理所有类型的文件(包括图像、音频等二进制文件),字符流则专门用于处理字符文件(如文本文件)。

字节流

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
// FileInputStream:从文件读取字节数据
// FileOutputStream:向文件写入字节数据
// 读取文件
import java.io.FileInputStream;
import java.io.IOException;

public class ByteFileRead {
public static void main(String[] args) {
try (FileInputStream fileInputStream = new FileInputStream("input.txt")) {
int content;
while ((content = fileInputStream.read()) != -1) {
System.out.print((char) content); // 将读取的字节转换为字符并打印
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 写入文件
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteFileWrite {
public static void main(String[] args) {
String data = "Hello, world!";

try (FileOutputStream fileOutputStream = new FileOutputStream("output.txt")) {
fileOutputStream.write(data.getBytes()); // 将字符串数据转换为字节并写入文件
} catch (IOException e) {
e.printStackTrace();
}
}
}

字符流,专门用来处理字符数据、文本文件。

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
// FileReader:从文件读取字符数据
// FileWriter:向文件写入字符数据
import java.io.FileReader;
import java.io.IOException;

public class CharFileRead {
public static void main(String[] args) {
try (FileReader fileReader = new FileReader("input.txt")) {
int content;
while ((content = fileReader.read()) != -1) {
System.out.print((char) content); // 将读取的字符打印到控制台
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

// 写入文件
import java.io.FileWriter;
import java.io.IOException;

public class CharFileWrite {
public static void main(String[] args) {
String data = "Hello, world!";

try (FileWriter fileWriter = new FileWriter("output.txt")) {
fileWriter.write(data); // 直接写入字符数据
} catch (IOException e) {
e.printStackTrace();
}
}
}

缓冲流, 提供了一个缓冲区,可以减少对硬盘的读取次数,从而提高性能。

1
2
3
4
// BufferedReader:缓冲字符输入流,用于提高读取效率。
// BufferedWriter:缓冲字符输出流,用于提高写入效率。
// BufferedInputStream:缓冲字节输入流。
// BufferedOutputStream:缓冲字节输出流。

RandomAccessFile,随机访问文件。这个类似C语言的FILE指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.RandomAccessFile;
import java.io.IOException;

public class RandomAccessFileExample {
public static void main(String[] args) {
try (RandomAccessFile file = new RandomAccessFile("example.txt", "rw")) {
file.writeUTF("Hello, World!"); // 写入字符串
file.seek(0); // 将文件指针移动到文件开头
String data = file.readUTF(); // 读取字符串
System.out.println("Read from file: " + data);
} catch (IOException e) {
e.printStackTrace();
}
}
}

标准输入输出

System.out 是 Java 中标准输出流,是 PrintStream 类型的对象

System.in 是 Java 中标准输入流, 是 InputStream 类型的对象,读取的是字节数据。对于字符数据,通常会使用 Scanner 或 BufferedReader 类

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Scanner;

public class ScannerInput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your name:");
String name = scanner.nextLine(); // 读取一行字符串
System.out.println("Enter your age:");
int age = scanner.nextInt();
System.out.println("Name: " + name + ", Age: " + age);
scanner.close();
}
}

格式化输出

1
System.out.printf(String format, Object... args);

网络库

java.net 包提供了构建网络应用的基础类和接口

Go

文件IO

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
os.Open  // 用于打开一个文件,只读模式。
os.Create // 用于创建一个新文件,如果文件已存在,则会覆盖它
os.OpenFile // 指定模式打开文件
func OpenFile(name string, flag int, perm FileMode) (*File, error)
file, err := os.OpenFile("example.txt", os.O_APPEND|os.O_WRONLY, 0644)

// 移动文件指针位置
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
position, err := file.Seek(0, io.SeekCurrent) // 返回文件当前位置

// 按字节读取文件, 一次最多读取len(p)字节到buf
Read(p []byte) (n int, err error)
// 指定offset读取
ReadAt(p []byte, off int64) (n int, err error)

buf := make([]byte, 1024)
n, err := file.Read(buf)


// ioutil.ReadFile 读取整个文件
content, err := ioutil.ReadFile("example.txt")

// 写入字符串到文件
_, err = file.WriteString("Hello, Golang file I/O!")
// 写入字节序列到文件
data := []byte("Hello, Golang byte data!")
_, err = file.Write(data)
// 在offset随机写文件
WriteAt(p []byte, off int64) (n int, err error)

golang 格式化参数有所特别

1
2
3
4
5
6
7
8
9
10
11
%v	值的默认格式表示
%+v 带字段名的结构体表示

%c 对应 Unicode 码点的字符
%d 十进制表示
%x 十六进制(小写字母)
%X 十六进制(大写字母)

%s 字符串
%.nf: 指定小数点后 n 位
%m.nf 设置宽度和小数位数

标准输入输出

golang提供fmt包用于标准输入输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 输出
fmt.Print("Hello")
fmt.Println("Hello")
// 格式化输出
fmt.Printf("My name is %s and I am %d years old.\n", name, age)
// fmt.Fprint() 将格式化的输出写入到指定的 io.Writer
fmt.Fprint(os.Stdout, "Hello, world!")
fmt.Fprintf(file, "Hello, file!")

// fmt.Scanf() 标准输入
fmt.Scanf("%s %d", &name, &age)
fmt.Scanln(&name)

// 字符串格式化
result := fmt.Sprintf("Name: %s, Age: %d", name, age)
fmt.Sscanf(input, "%s %d", &name, &age)

网络库

Go提供了 net 包 用于网络编程

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
// 客户端
func main() {
// 连接到 TCP 服务器
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println("Error dialing:", err)
os.Exit(1)
}
defer conn.Close()

// 向服务器发送数据
_, err = conn.Write([]byte("Hello, Server!"))
if err != nil {
fmt.Println("Error sending message:", err)
return
}

// 读取服务器响应
buffer := make([]byte, 1024)
n, err := conn.Read(buffer)
if err != nil {
fmt.Println("Error reading response:", err)
return
}

// 打印接收到的响应
fmt.Printf("Received: %s\n", string(buffer[:n]))
}

// 服务端
func main() {
// 在本地启动一个 TCP 服务器,监听端口 8080
listen, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("Error starting server:", err)
os.Exit(1)
}
defer listen.Close()

fmt.Println("Server started, waiting for connections...")

// 接受客户端连接
for {
conn, err := listen.Accept()
if err != nil {
fmt.Println("Error accepting connection:", err)
continue
}
defer conn.Close()

// 读取客户端消息
buffer := make([]byte, 1024)
n, err := conn.Read(buffer)
if err != nil {
fmt.Println("Error reading from connection:", err)
}

// 输出接收到的消息
fmt.Printf("Received: %s\n", string(buffer[:n]))

// 向客户端发送响应
_, err = conn.Write([]byte("Hello, Client!"))
if err != nil {
fmt.Println("Error sending response:", err)
}
}
}

命令行库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func main() {
// 定义命令行参数
var name string
var age int
var isAdmin bool

// 通过 flag 包解析命令行标志
flag.StringVar(&name, "name", "Guest", "Your name")
flag.IntVar(&age, "age", 18, "Your age")
flag.BoolVar(&isAdmin, "admin", false, "Is admin?")

flag.Parse()

fmt.Printf("Name: %s\n", name)
fmt.Printf("Age: %d\n", age)
fmt.Printf("Is Admin: %v\n", isAdmin)
}

// 执行, go run main.go -name=John -age=30 -admin=true

Python

文件IO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 打开文件
# 文件打开模式
# 'r':只读模式,文件必须存在。
# 'w':写入模式,若文件已存在则覆盖,不存在则创建。
# 'a':追加模式,在文件末尾追加内容,若文件不存在,则创建。
# 'b':二进制模式(如读取或写入图片、音频等)
file = open('filename', mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

with open('example.txt', 'r') as file:
content = file.read() # 读取全部内容
print(content)

file.seek(0) # 文件指针移动到开头
first_10_chars = file.read(10) # 读取前10个字符
print(first_10_chars)

print(file.tell()) # 输出文件指针当前位置

file.write("Hello, World!\n") # 写入内容

lines = ['Line 1\n', 'Line 2\n', 'Line 3\n']
file.writelines(lines) # 写入多行
file.flush() # 立即写入数据

os 文件操作

1
2
3
4
5
os.remove('example.txt')  # 删除文件
# 获取文件状态信息
stat_info = os.stat('example.txt')
# 创建目录
os.mkdir('new_directory')

标准输入输出

print() 函数用于标准输出, 同时也支持格式化输出

1
2
3
4
name = "Alice"
age = 25
print(f"My name is {name}, and I am {age} years old.")
print("My name is {}, and I am {} years old.".format(name, age))

input()用于标准输入, input读到的类型都是字符串

1
2
3
4
name = input("Enter your name: ")
print(f"Hello, {name}!")

age = int(input("Enter your age: "))

网络库

socket编程

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
# 服务端
import socket

# 创建 TCP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定服务器地址和端口
server_address = ('localhost', 65432)
server_socket.bind(server_address)
server_socket.listen(1)
print("Waiting for a connection...")
connection, client_address = server_socket.accept()
print(f"Connection from {client_address}")

try:
data = connection.recv(1024)
print(f"Received: {data.decode()}")
message = "Hello, Client!"
connection.sendall(message.encode())

finally:
connection.close()

# 客户端
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 65432) # 服务器地址和端口
client_socket.connect(server_address)

try:
message = 'Hello, Server!'
client_socket.sendall(message.encode()) # 发送数据(注意要编码成字节)
data = client_socket.recv(1024) # 接收数据(最多 1024 字节)
print(f"Received from server: {data.decode()}") # 解码并打印数据

finally:
# 关闭连接
client_socket.close()

argparse 命令行输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import argparse

# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(description="A simple command-line tool")

# 添加参数
parser.add_argument('name', type=str, help="Your name")
parser.add_argument('age', type=int, help="Your age")
parser.add_argument('--admin', action='store_true', help="Are you an admin?")

# 解析命令行参数
args = parser.parse_args()

# 使用参数
print(f"Name: {args.name}")
print(f"Age: {args.age}")
print(f"Admin: {args.admin}")

json 序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import json
data = {
"name": "Alice",
"age": 25,
"city": "New York"
}

# 打开文件并写入 JSON 数据
with open("data.json", "w") as json_file:
json.dump(data, json_file, indent=4)
# 从文件中读取 JSON 数据
with open("data.json", "r") as json_file:
data = json.load(json_file)
# 对象编码
json_string = json.dumps(data, indent=4)
# 对象解码
data = json.loads(json_string)