truncate 系统调用及示例

了解Linux中truncate系统调用的功能、语法及实用示例,帮助你高效管理文件大小,truncate系统调用用于将文件截断到指定长度。如果指定长度小于文件当前长度,则文件末尾被截断;如果指定长度大于文件当前长度,则文件被扩展,扩展部分填充为零。

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

truncate - 截断文件

函数介绍

truncate系统调用用于将文件截断到指定长度。如果指定长度小于文件当前长度,则文件末尾被截断;如果指定长度大于文件当前长度,则文件被扩展,扩展部分填充为零。

函数原型

1
2
3
4
5
#include <unistd.h>
#include <sys/types.h>

int truncate(const char *path, off_t length);

功能

根据文件路径将文件截断或扩展到指定长度。

参数

  • const char *path: 文件路径名

  • off_t length: 目标文件长度(字节)

返回值

  • 成功时返回0

失败时返回-1,并设置errno:

  • EACCES: 权限不足

  • EFBIG: 长度参数过大

  • EIO: I/O错误

  • EISDIR: 路径指向目录

  • ELOOP: 符号链接循环

  • ENAMETOOLONG: 路径名过长

  • ENOENT: 文件不存在

  • ENOTDIR: 路径前缀不是目录

  • EPERM: 操作不被允许

  • EROFS: 文件在只读文件系统上

  • ETXTBSY: 文件是正在执行的程序

相似函数

  • ftruncate(): 通过文件描述符截断文件

  • open()配合O_TRUNC标志

示例代码

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

int main() {
int fd;
struct stat stat_buf;

printf("=== Truncate函数示例 ===\n");

// 示例1: 基本的文件截断操作
printf("\n示例1: 基本的文件截断操作\n");

// 创建测试文件并写入数据
fd = open("test_truncate.txt", O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd == -1) {
perror("创建测试文件失败");
exit(EXIT_FAILURE);
}

// 写入较长的数据
const char *original_data =
"This is a long piece of text that will be used to demonstrate "
"the truncate function. It contains multiple sentences and is "
"quite lengthy to show how truncation works.";

if (write(fd, original_data, strlen(original_data)) == -1) {
perror("写入原始数据失败");
close(fd);
exit(EXIT_FAILURE);
}

printf("写入原始数据,长度: %ld 字节\n", (long)strlen(original_data));
close(fd);

// 获取原始文件状态
if (stat("test_truncate.txt", &stat_buf) == -1) {
perror("获取文件状态失败");
} else {
printf("原始文件大小: %ld 字节\n", stat_buf.st_size);
}

// 使用truncate截断文件到50字节
printf("\n使用truncate将文件截断到50字节...\n");
if (truncate("test_truncate.txt", 50) == -1) {
perror("截断文件失败");
} else {
printf("文件截断成功\n");
}

// 检查截断后的文件大小
if (stat("test_truncate.txt", &stat_buf) == -1) {
perror("获取截断后文件状态失败");
} else {
printf("截断后文件大小: %ld 字节\n", stat_buf.st_size);
}

// 读取截断后的数据验证
fd = open("test_truncate.txt", O_RDONLY);
if (fd != -1) {
char buffer&#91;100];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
if (bytes_read > 0) {
buffer&#91;bytes_read] = '\0';
printf("截断后文件内容: %s\n", buffer);
}
close(fd);
}

// 示例2: 扩展文件
printf("\n示例2: 扩展文件\n");

// 使用truncate将文件扩展到100字节
printf("使用truncate将文件扩展到100字节...\n");
if (truncate("test_truncate.txt", 100) == -1) {
perror("扩展文件失败");
} else {
printf("文件扩展成功\n");
}

// 检查扩展后的文件大小
if (stat("test_truncate.txt", &stat_buf) == -1) {
perror("获取扩展后文件状态失败");
} else {
printf("扩展后文件大小: %ld 字节\n", stat_buf.st_size);
}

// 读取扩展后的数据
fd = open("test_truncate.txt", O_RDONLY);
if (fd != -1) {
char buffer&#91;150];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
if (bytes_read > 0) {
printf("扩展后文件前%d字节内容:\n", (int)bytes_read);
// 打印可见字符
for (int i = 0; i < bytes_read && i < 60; i++) {
if (buffer&#91;i] >= 32 && buffer&#91;i] <= 126) {
putchar(buffer&#91;i]);
} else {
printf("&#91;%02x]", (unsigned char)buffer&#91;i]);
}
}
printf("\n");
}
close(fd);
}

// 示例3: 截断到0字节(清空文件)
printf("\n示例3: 截断到0字节(清空文件)\n");

printf("将文件截断到0字节...\n");
if (truncate("test_truncate.txt", 0) == -1) {
perror("清空文件失败");
} else {
printf("文件清空成功\n");
}

if (stat("test_truncate.txt", &stat_buf) == -1) {
perror("获取清空后文件状态失败");
} else {
printf("清空后文件大小: %ld 字节\n", stat_buf.st_size);
}

// 示例4: 不同长度的截断演示
printf("\n示例4: 不同长度的截断演示\n");

// 重新创建文件并写入数据
fd = open("test_truncate.txt", O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd != -1) {
const char *test_data = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (write(fd, test_data, strlen(test_data)) != -1) {
printf("重新写入测试数据: %s\n", test_data);
}
close(fd);
}

// 演示不同长度的截断
off_t lengths&#91;] = {5, 15, 30, 50};
for (int i = 0; i < 4; i++) {
printf("截断到%ld字节: ", lengths&#91;i]);
if (truncate("test_truncate.txt", lengths&#91;i]) == -1) {
printf("失败 - %s\n", strerror(errno));
} else {
if (stat("test_truncate.txt", &stat_buf) == -1) {
printf("获取状态失败\n");
} else {
printf("成功,新大小: %ld字节\n", stat_buf.st_size);

// 读取并显示内容
fd = open("test_truncate.txt", O_RDONLY);
if (fd != -1) {
char buffer&#91;100];
ssize_t bytes_read = read(fd, buffer, stat_buf.st_size);
if (bytes_read > 0) {
buffer&#91;bytes_read] = '\0';
printf(" 内容: %s\n", buffer);
}
close(fd);
}
}
}
}

// 示例5: 错误处理演示
printf("\n示例5: 错误处理演示\n");

// 尝试截断不存在的文件
if (truncate("nonexistent_file.txt", 100) == -1) {
printf("截断不存在的文件: %s\n", strerror(errno));
}

// 尝试对只读文件系统上的文件操作
// 这个测试可能需要特殊环境,我们只演示概念
printf("对只读文件系统操作会返回EROFS错误\n");

// 尝试使用负数长度
if (truncate("test_truncate.txt", -10) == -1) {
printf("使用负数长度: %s\n", strerror(errno));
}

// 尝试对目录操作
if (truncate(".", 100) == -1) {
printf("对目录截断: %s\n", strerror(errno));
}

// 示例6: 实际应用场景
printf("\n示例6: 实际应用场景\n");

// 场景1: 日志文件轮转
printf("场景1: 日志文件轮转\n");
int log_fd = open("application.log", O_CREAT | O_RDWR | O_APPEND, 0644);
if (log_fd != -1) {
// 模拟写入大量日志
for (int i = 0; i < 100; i++) {
char log_entry&#91;100];
sprintf(log_entry, "Log entry %d: Application is running normally\n", i);
write(log_fd, log_entry, strlen(log_entry));
}
close(log_fd);

// 检查日志文件大小
if (stat("application.log", &stat_buf) == 0) {
printf("日志文件大小: %ld 字节\n", stat_buf.st_size);

// 如果文件太大,截断到1KB
if (stat_buf.st_size > 1024) {
printf("日志文件过大,截断到1KB...\n");
if (truncate("application.log", 1024) == -1) {
perror("日志文件截断失败");
} else {
printf("日志文件截断成功\n");
}
}
}

unlink("application.log");
}

// 场景2: 临时文件大小控制
printf("场景2: 临时文件大小控制\n");
int temp_fd = open("temp_file.dat", O_CREAT | O_RDWR, 0644);
if (temp_fd != -1) {
// 创建一个大文件
char large_data&#91;1000];
memset(large_data, 'X', sizeof(large_data));
for (int i = 0; i < 10; i++) {
write(temp_fd, large_data, sizeof(large_data));
}
close(temp_fd);

if (stat("temp_file.dat", &stat_buf) == 0) {
printf("临时文件原始大小: %ld 字节\n", stat_buf.st_size);

// 将文件大小调整为5KB
printf("调整临时文件大小到5KB...\n");
if (truncate("temp_file.dat", 5120) == -1) {
perror("调整文件大小失败");
} else {
printf("文件大小调整成功\n");

if (stat("temp_file.dat", &stat_buf) == 0) {
printf("调整后文件大小: %ld 字节\n", stat_buf.st_size);
}
}
}

unlink("temp_file.dat");
}

// 清理资源
printf("\n清理资源...\n");
if (unlink("test_truncate.txt") == -1) {
perror("删除测试文件失败");
} else {
printf("成功删除测试文件\n");
}

return 0;
}

https://www.calcguide.tech/2025/08/08/truncate-系统调用及示例/

data-ad-format="auto" data-full-width-responsive="true">