新增韦东山文件IO内容
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,3 +13,4 @@
|
||||
!**/*.md
|
||||
!**/makefile
|
||||
!**/Makefile
|
||||
!**/*.csv
|
||||
|
||||
@@ -33,8 +33,8 @@ FILE *fopen(const char *path, const char *mode);
|
||||
*/
|
||||
int fclose(FILE *fp);
|
||||
|
||||
int fputc(FILE *stream);
|
||||
int fgetc(int c, FILE *stream);
|
||||
int fputc(int c, FILE *stream);
|
||||
int fgetc(FILE *stream);
|
||||
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
/**
|
||||
@@ -64,8 +64,6 @@ int printf(const char *restrict format, ...);
|
||||
* 常用于 fprintf(stderr,...)
|
||||
*/
|
||||
int fprintf(FILE *restrict stream, const char *restrict format, ...);
|
||||
|
||||
// TODO:
|
||||
int dprintf(int fd, const char *restrict format, ...);
|
||||
|
||||
/**
|
||||
@@ -146,6 +144,7 @@ fflush();
|
||||
|
||||
/**
|
||||
* @prarm: mode
|
||||
* 三种缓冲模式:
|
||||
* _IONBF
|
||||
* _IOLBF
|
||||
* _IOFBF
|
||||
@@ -200,20 +199,48 @@ FILE *tmpfile(void);
|
||||
- write
|
||||
- lsee
|
||||
|
||||
可以使用`./open file &`来后台运行一个程序。
|
||||
然后通过`ps`查看进程号
|
||||
然后进入`/proc/进程号/fd`查看文件描述符
|
||||
前三个是标准输入输出错误,后面的是打开的文件描述符
|
||||
|
||||
```c
|
||||
|
||||
/**
|
||||
* flag:
|
||||
*
|
||||
* r -> O_RDONLY
|
||||
* r+ -> O_RDWR
|
||||
* w -> O_WRONLY | O_CREAT | O_TRUNC
|
||||
* w+ -> O_RDWR | O_TRUNC | O_CREAT
|
||||
*
|
||||
* O_RDONLY 只读
|
||||
* O_WRONLY 只写
|
||||
* O_RDWR 读写
|
||||
* O_CREAT 创建
|
||||
* O_TRUNC 截断
|
||||
* O_APPEND 追加
|
||||
* O_EXCL 排他(若要创建的文件已存在则报错)
|
||||
* O_NONBLOCK 非阻塞
|
||||
* O_SYNC 同步
|
||||
* O_DSYNC 数据同步
|
||||
* O_RSYNC 读同步
|
||||
* O_DIRECT 直接IO
|
||||
* O_LARGEFILE 大文件
|
||||
* O_DIRECTORY 目录
|
||||
* O_NOFOLLOW 不跟踪符号链接
|
||||
* O_CLOEXEC close-on-exec
|
||||
* O_PATH 仅打开目录
|
||||
* O_TMPFILE 临时文件
|
||||
* O_NOCTTY 不分配控制终端
|
||||
*
|
||||
* 如果有creat就必须用三参数的形式
|
||||
* C语言没有重载,这是变参函数
|
||||
*
|
||||
* @prarm: pathname 文件路径
|
||||
* @prarm: flags 文件打开方式
|
||||
* @prarm: mode 文件权限
|
||||
* 假如0666,就是rw-rw-rw-,110110110
|
||||
*
|
||||
*/
|
||||
int open(const char *pathname, int flags);
|
||||
@@ -222,14 +249,12 @@ int open(const char *pathname, int flags, mode_t mode);
|
||||
int close(int fd);
|
||||
|
||||
/**
|
||||
* read from a file descriptor
|
||||
*
|
||||
* @return 读取的字节数,失败返回-1
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* write to a file descriptor
|
||||
* 想要控制写入的位置,需要使用lseek
|
||||
*
|
||||
* @return 写入的字节数,失败返回-1
|
||||
*/
|
||||
@@ -248,6 +273,16 @@ off_t lseek(int fd, offt offset, int whence);
|
||||
|
||||
```
|
||||
|
||||
### 例题:通过文件IO处理csv表格
|
||||
```csv
|
||||
,语文,数学,英语,总分,评价
|
||||
张三,90,91,92,,
|
||||
李四,80,81,82,,
|
||||
王五,70,71,72,,
|
||||
```
|
||||
思路:逐行处理
|
||||
可以使用16进制查看工具
|
||||
|
||||
|
||||
### 文件IO与标准IO的区别
|
||||
区别:响应速度&吞吐量
|
||||
|
||||
205
C13-Linux系统编程/fs/W_process_excel.c
Normal file
205
C13-Linux系统编程/fs/W_process_excel.c
Normal file
@@ -0,0 +1,205 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if 1
|
||||
# define debug(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
# define debug(fmt, args...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 读取一行
|
||||
* @details
|
||||
* 循环读入一个字符
|
||||
* 如何判断读完一行? 读到0x0d, 0x0a
|
||||
*
|
||||
* @param fd
|
||||
* @param buf
|
||||
*
|
||||
* @return int 读到的一行数据的数据个数( n>=0 )
|
||||
* -1: 读到文件尾部或者出错
|
||||
*/
|
||||
static int read_line(int fd, unsigned char *buf)
|
||||
{
|
||||
unsigned char c;
|
||||
int len;
|
||||
int i = 0;
|
||||
int err = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
len = read(fd, &c, 1);
|
||||
if (len <= 0)
|
||||
{
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c != '\n' && c != '\r')
|
||||
{
|
||||
buf[i] = c;
|
||||
i++;
|
||||
}
|
||||
else /* 碰到回车换行 */
|
||||
{
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
if (err && (0 == i))
|
||||
/* 读到文件尾部且无有效数据 */
|
||||
return -1;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 处理一行的数据, 计算出总分和评价
|
||||
* @details
|
||||
*
|
||||
* @param data_buf
|
||||
* @param result_buf
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static void process_data(unsigned char *data_buf, unsigned char *result_buf)
|
||||
{
|
||||
/**
|
||||
* eg1: data_buf=",语文,数学,英语,总分,评价"
|
||||
* result_buf=",语文,数学,英语,总分,评价"
|
||||
*
|
||||
* eg2: data_buf="张三,90,91,92,,"
|
||||
* result_buf="张三,90,91,92,273,A+"
|
||||
*
|
||||
*/
|
||||
|
||||
char name[100];
|
||||
int scores[3];
|
||||
int sum;
|
||||
char *levels[] = {"A+", "A", "B"};
|
||||
int level;
|
||||
|
||||
// debug("data_buf[0]: %x\n", data_buf[0]);
|
||||
if (0xef == data_buf[0]) /* 对于UTF-8, 前三个字符是0xef 0xbb 0xbf */
|
||||
{
|
||||
strcpy(result_buf, data_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// debug("data_buf: %s\n", data_buf);
|
||||
// debug("进入了\n");
|
||||
/**
|
||||
* @brief 从字符串得到数据
|
||||
* @details
|
||||
* 拆分信息: scanf分隔符
|
||||
* %[^,]: 读数据直到碰到逗号
|
||||
*
|
||||
*/
|
||||
sscanf(data_buf,
|
||||
"%[^,],%d,%d,%d,,",
|
||||
name,
|
||||
&scores[0],
|
||||
&scores[1],
|
||||
&scores[2]);
|
||||
|
||||
debug("name: %s, scores: %d, %d, %d\n",
|
||||
name,
|
||||
scores[0],
|
||||
scores[1],
|
||||
scores[2]);
|
||||
|
||||
sum = scores[0] + scores[1] + scores[2];
|
||||
if (sum >= 270)
|
||||
level = 0;
|
||||
else if (sum >= 240)
|
||||
level = 1;
|
||||
else
|
||||
level = 2;
|
||||
|
||||
sprintf(result_buf,
|
||||
"%s,%d,%d,%d,%d,%s",
|
||||
name,
|
||||
scores[0],
|
||||
scores[1],
|
||||
scores[2],
|
||||
sum,
|
||||
levels[level]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 处理csv表格
|
||||
* @details
|
||||
* Usage: ./W_process_excel data.csv result.csv
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd_data, fd_result;
|
||||
int len;
|
||||
unsigned char data_buf[1000];
|
||||
unsigned char result_buf[1000];
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Usage: %s data.csv result.csv\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd_data = open(argv[1], O_RDONLY);
|
||||
if (fd_data < 0)
|
||||
{
|
||||
perror("open data.csv");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("data file fd: %d\n", fd_data);
|
||||
|
||||
fd_result = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd_result < 0)
|
||||
{
|
||||
perror("open result.csv");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("result file fd: %d\n", fd_result);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* 读取1行 */
|
||||
len = read_line(fd_data, data_buf);
|
||||
if (-1 == len)
|
||||
break;
|
||||
|
||||
// if (len != 0)
|
||||
// debug("%s\n\r", data_buf);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
/* 处理1行 */
|
||||
process_data(data_buf, result_buf);
|
||||
|
||||
/* 写入结果文件 */
|
||||
write(fd_result, result_buf, strlen(result_buf));
|
||||
write(fd_result, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd_data);
|
||||
close(fd_result);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
4
C13-Linux系统编程/fs/data.csv
Normal file
4
C13-Linux系统编程/fs/data.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
,语文,数学,英语,总分,评价
|
||||
张三,90,91,92,,
|
||||
李四,80,81,82,,
|
||||
王五,70,71,72,,
|
||||
|
4
C13-Linux系统编程/fs/result.csv
Normal file
4
C13-Linux系统编程/fs/result.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
,语文,数学,英语,总分,评价
|
||||
张三,90,91,92,273,A+
|
||||
李四,80,81,82,243,A
|
||||
王五,70,71,72,213,B
|
||||
|
@@ -1,8 +1,15 @@
|
||||
# Linux-C-Notes
|
||||
Linux环境C语言开发学习笔记
|
||||
## 课程地址
|
||||
|
||||
主要是李慧芹老师的课程,讲的比较清晰。同时韦东山老师的课,讲的比较杂和跳跃,正好把知识点作为补充。
|
||||
韦东山课程的代码以"W"开头来命名。
|
||||
|
||||
[史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV18p4y167Md/?spm_id_from=333.999.0.0&vd_source=4e03f52e94cfa281cde032856b1f93a7)
|
||||
|
||||
[【第4篇】嵌入式Linux应用开发基础知识_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1kk4y117Tu/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=4e03f52e94cfa281cde032856b1f93a7)
|
||||
|
||||
|
||||
## 本仓库内容
|
||||
教学过程中所有的课程笔记和代码示例。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user