【linux草鞋应用编程系列】_1_ 开篇_系统调用IO接口与标准IO接口
最近学习linux系统下的应用编程,参考书籍是那本称为神书的《Unix环境高级编程》,个人感觉神书不是写给草鞋看的,而是
写给大神看的,如果没有一定的基础那么看这本书可能会感到有些头重脚轻的感觉。我自己就是这样,比方说看进程间通信信号量章
节的时候,开始感觉就很迷糊,因此也就想在这里写一些文字,给和我一样的草鞋分享一些自己的学习经历(算不上经验吧)。
环境: windows7, VMware 9.0
操作系统版本: RHEL 5.5
内核版本: 2.6.18-194.el5
Gcc版本: gcc 版本 4.1.2 20080704 (Red Hat 4.1.2-48) 【2008年7月4日构建的】
【linux草鞋应用编程系列】的系列文章,欢迎批评指正。 欢迎转载,如果您愿意可以添加本系列文章的链接,即本草鞋的在博客园
的链接。
正文中的函数的原型都是通过 man page 查看和复制到,查看的时候如果与这里的不一样,请以查看的为准, 因为不同的内核
版本支持的函数,以及函数的参数可能存在一些出入。
废话少说,下面开始正题。
开篇: 系统调用IO接口与标准IO接口
正文:
- NAME
- open, creat - open and possibly create a file or device
- SYNOPSIS
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int open(const char *pathname, //要打开的文件的路径和文件名
- int flags); //打开方式
- int open(const char *pathname, //要打开的文件的路径和文件名
- int flags, //打开方式 , 这个格式的调用,表示使用了 O_CREAT 打开方式标志。
- mode_t mode); //打开后文件的权限
- int creat(const char *pathname, //要创建的文件的路径和文件名
- mode_t mode); //创建后文件的权限
- mode must be specified when O_CREAT is in the flags, and is ignored otherwise.
- creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC.
- NAME
- read - read from a file descriptor
- SYNOPSIS
- #include <unistd.h>
- ssize_t read( int fd, //要读取文件的文件描述符
- void *buf, //读取数据存储的缓冲区
- size_t count); //要读取字节数
返回值:
- NAME
- write - write to a file descriptor
- SYNOPSIS
- #include <unistd.h>
- ssize_t write(int fd, //要写入文件的文件描述符
- const void *buf, //待写入数据的缓冲区
- size_t count); //要写入的字节数
- 返回值:
- 成功返回写入到字节数, 返回0 表示没有写入任何东西。
- 失败返回 - 1 .
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #define BUF_LEN 1024
- int main(int argc, char* argv[])
- {
- int fd_src,
- fd_dst;
- char buf[BUF_LEN];
- int ret;
- int ret_r;
- if(argc < )
- {
- printf("usage: cpfile file_src file_dst\n");
- printf("\tfile_src:file want to copy\n");
- printf("\tfile_dst:file where to store\n");
- exit();
- }
- fd_src=open(argv[], O_RDONLY);
- if(- == fd_src )
- {
- strcpy(buf,"open ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- fd_dst=open(argv[],O_WRONLY|O_CREAT,);
- if(- == fd_dst )
- {
- strcpy(buf,"open ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- do
- {
- memset(buf,,sizeof(buf));
- ret_r=read(fd_src,buf,sizeof(buf) );
- if(- == ret)
- {
- strcpy(buf,"read ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- ret=write(fd_dst,buf,ret_r);
- if(- == ret)
- {
- strcpy(buf,"write ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- }while( ret_r != );
- close(fd_src);
- close(fd_dst);
- return ;
- }
- NAME
- opendir - open a directory
- SYNOPSIS
- #include <sys/types.h>
- #include <dirent.h>
- DIR *opendir(const char *name); //要打开的目录的路径和目录名
- READDIR() Linux Programmer’s Manual READDIR()
- NAME
- readdir - read a directory
- SYNOPSIS
- #include <sys/types.h>
- #include <dirent.h>
- struct dirent *readdir(DIR *dir); //要读取的目录的指针
- struct dirent {
- ino_t d_ino; /* inode number */
- off_t d_off; /* offset to the next dirent */
- unsigned short d_reclen; /* length of this record */
- unsigned char d_type; /* type of file */ //文件类型
- char d_name[]; /* filename */ //文件名
- };
- #include <stdio.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <stdlib.h>
- int main(int argc, char* argv[])
- {
- DIR *dir=NULL;
- struct dirent *file=NULL;
- if(argc < ) //如果没有指定要显示的目录,就显示当前目录的的文件
- {
- dir=opendir("./");
- if(!dir)
- {
- perror("open");
- exit();
- }
- else
- {
- while(file=readdir(dir))
- printf("%s\t",file->d_name);
- }
- putchar('\n');
- closedir(dir);
- exit();
- }
- dir=opendir(argv[]);
- if(!dir)
- {
- perror("open");
- exit();
- }
- while(file=readdir(dir))
- printf("%s",file->d_name);
- printf("\n");
- closedir(dir);
- return ;
- }
- [root@localhost ls]# ls
- main.c
- [root@localhost ls]# gcc -o dir main.c
- [root@localhost ls]# ./dir
- dir main.c .. .
- [root@localhost ls]#
- ACCESS() Linux Programmer’s Manual ACCESS()
- NAME
- access - check user’s permissions for a file
- SYNOPSIS
- #include <unistd.h>
- int access( const char *pathname, //要检查的文件路径和文件名
- int mode); //要检测的内容,如文件是否存在 F_OK 等
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #define BUF_LEN 1024
- int main(int argc, char* argv[])
- {
- int fd_src,
- fd_dst;
- char buf[BUF_LEN];
- int ret;
- int ret_r;
- if(argc < ) //参数小于3个,就打印提示信息
- {
- printf("usage: cpfile file_src file_dst\n");
- printf("\tfile_src:which file want to copy\n");
- printf("\tfile_dst:file where to store\n");
- printf("\n\tIf the file_src and file_dst without path,"
- "will operation at current directory\n");
- exit();
- }
- //检测目标文件是否存在
- if( ! access(argv[],F_OK) )
- {
- printf("%s exist,do you want to overwrite it?(y/n):",argv[]);
- buf[]=getchar();
- if( 'n' == buf[] )
- exit();
- }
- fd_src=open(argv[], O_RDONLY);
- if(- == fd_src )
- {
- strcpy(buf,"open ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- fd_dst=open(argv[],O_WRONLY|O_CREAT,);
- if(- == fd_dst )
- {
- strcpy(buf,"open ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- do
- {
- memset(buf,,sizeof(buf));
- ret_r=read(fd_src,buf,sizeof(buf) );
- if(- == ret)
- {
- strcpy(buf,"read ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- ret=write(fd_dst,buf,ret_r);
- if(- == ret)
- {
- strcpy(buf,"write ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- }while( ret_r != );
- close(fd_src);
- close(fd_dst);
- return ;
- }
- STAT() Linux Programmer’s Manual STAT()
- NAME
- stat, fstat, lstat - get file status
- SYNOPSIS
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- int stat(const char *path, //要查看的文件的路径和文件名
- struct stat *buf); //输出参数, 用于存储文件信息的结构体指针
- int fstat(int filedes, //打开的文件的文件描述符
- struct stat *buf); //输出参数, 用于存储文件信息的结构体指针
- int lstat(const char *path, //要查看的文件的路径和文件名
- struct stat *buf); //输出参数, 用于存储文件信息的结构体指针
返回值:
- struct stat {
- dev_t st_dev; /* ID of device containing file */
- ino_t st_ino; /* inode number */
- mode_t st_mode; /* protection */
- nlink_t st_nlink; /* number of hard links */ //硬连接数
- uid_t st_uid; /* user ID of owner */ //用户ID
- gid_t st_gid; /* group ID of owner */ //组ID
- dev_t st_rdev; /* device ID (if special file) */ //特殊文件ID号
- off_t st_size; /* total size, in bytes */ //文件大小
- blksize_t st_blksize; /* blocksize for filesystem I/O */ //文件IO的块大小
- blkcnt_t st_blocks; /* number of blocks allocated */ //文件使用的块数目
- time_t st_atime; /* time of last access */ //最后访问时间
- time_t st_mtime; /* time of last modification */ //最后修改时间
- time_t st_ctime; /* time of last status change */ //最后
- };
- #include <stdio.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- #include <string.h>
- #define BUF_SIZE 512
- //定义一个函数解析文件信息
- void show_stat(char buf[] ,struct stat f_stat)
- {
- printf("File : %s\n",buf);
- printf("\tuser id: %d\n", f_stat.st_uid);
- printf("\tgroup id: %d\n",f_stat.st_gid);
- printf("\tfile size:%.3fK\n", . * f_stat.st_size /); //显示3位小数
- printf("\tfile ulink:%d\n",f_stat.st_nlink);
- }
- //定义一个函数遍历目录
- void dir(const char *path)
- {
- DIR *dir=NULL; //打开的目录
- struct dirent *f_dir=NULL; //存储目录项
- char buf[]={};
- struct stat f_stat={}; //用来检测文件的信息
- int ret=;
- //打开目录
- dir=opendir(path);
- if(!dir)
- {
- strcpy(buf,"acces directory:");
- strcat(buf,path);
- perror(buf);
- exit();
- }
- //遍历目录
- while( f_dir = readdir(dir) )
- {
- //首先获取文件的路径和文件名
- strcpy(buf,path); //路径
- strcat(buf,"/"); //添加路径分割符号
- strcat(buf,f_dir->d_name); //文件名,buf包含路径名和文件名
- //获取目录项的属性
- ret=stat(buf,&f_stat);
- if(ret)
- {
- perror(buf);
- }
- if(S_ISDIR(f_stat.st_mode)) //如果是目录
- {
- printf("File : %s\n",f_dir->d_name);
- printf("\tA directory\n");
- }
- else if(S_ISREG(f_stat.st_mode))
- {
- show_stat(f_dir->d_name, f_stat);
- }
- else
- {
- printf("File : %s\n", f_dir->d_name);
- printf("\tother file type");
- }
- }//遍历目录结束
- }
- int main(int argc, char* argv[])
- {
- struct stat f_stat;
- int ret;
- char buf[BUF_SIZE];
- //首先判断是否有第二个参数, 没有就显示当前目录
- if( argc < )
- {
- dir("."); //注意这个地方,不能传递"./",因为dir函数中会添加最后一个反斜杠
- exit(); //显示完成就退出
- }
- //有第二个参数
- ret=stat(argv[],&f_stat);
- if(ret)
- {
- strcpy(buf,"access ");
- strcat(buf,argv[]);
- perror(buf);
- exit();
- }
- if(S_ISDIR(f_stat.st_mode)) //如果是目录
- {
- dir(argv[]);
- }
- if(S_ISREG(f_stat.st_mode)) //如果是文件
- {
- show_stat(argv[],f_stat);
- }
- return ;
- }
- CHDIR() Linux Programmer’s Manual CHDIR()
- NAME
- chdir, fchdir - change working directory
- SYNOPSIS
- #include <unistd.h>
- int chdir(const char *path); //要切换到的工作目录
- int fchdir(int fd); //通过打开的文件描述符,切换到打开的文件所在的目录
- GETCWD() Linux Programmer’s Manual GETCWD()
- NAME
- getcwd, get_current_dir_name, getwd - Get current working directory
- SYNOPSIS
- #include <unistd.h>
- char *getcwd( char *buf, //输出函数,用来存储当前路径的缓存区域
- size_t size); //缓存区域的大小
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h> //访问错误值代码
- extern int errno;
- int main(void)
- {
- char* buf=NULL;
- int ret;
- buf=(char *)malloc();
- buf=getcwd(buf,);
- if(!buf)
- {
- if(ERANGE == errno)
- buf=(char *)realloc(buf,);
- }
- buf=getcwd(buf,);
- printf("before change directroy: %s\n\n",buf);
- ret=chdir("/home/volcanol");
- if(ret)
- {
- perror("/home/volcanol");
- exit();
- }
- buf=getcwd(buf,);
- printf("after change directory:%s\n\n",buf);
- free(buf);
- return ;
- }
- #include <stdio.h>
- #include <unistd.h> //to use sleep()
- int main(void)
- {
- int i=;
- for(i=;i<;i++)
- {
- printf("%d ",i);
- sleep(); //为了查看效果,才加上sleep();
- }
- printf("\n");
- return ;
- }
执行的时候,可以看到 0、1、2、3、4 不是一个一个的输出,而是一起输出的。
- SETBUF() Linux Programmer’s Manual SETBUF()
- NAME
- setbuf, setbuffer, setlinebuf, setvbuf - stream buffering operations
- SYNOPSIS
- #include <stdio.h>
- void setbuf(FILE *stream,
- char *buf);
- void setbuffer(FILE *stream,
- char *buf,
- size_t size);
- void setlinebuf(FILE *stream); //设置为行缓冲, stream 表示设置缓冲的文件
- int setvbuf(FILE *stream, //要缓冲的文件,标准输出为 stdout
- char *buf, //缓冲区的首地址, =NULL 表示系统分配,
- int mode , //缓冲模式,行缓冲、全缓冲、无缓冲
- size_t size); //缓冲区大小
- #include <stdio.h>
- #include <unistd.h> //to use sleep()
- int main(void)
- {
- int i=;
- setvbuf( stdout, NULL , _IONBF , );
- for(i=;i<;i++)
- {
- printf("%d ",i);
- sleep(); //为了查看效果,才加上sleep();
- }
- printf("\n");
- return ;
- }
程序执行的过程中: 可以看到数字一个一个的输出,而不是一起输出。
- #include <stdio.h>
- #include <unistd.h> //to use sleep()
- int main(void)
- {
- int i=;
- char buf[]={};
- /*setvbuf(stdout, NULL, _IONBF ,0);*/
- setvbuf(stdout, buf , _IOLBF , );
- for(i=;i<;i++)
- {
- printf("%d ",i);
- sleep(); //为了查看效果,才加上sleep();
- }
- printf("\n");
- return ;
- }
可以看到数组0、1、2、3、4是一个一个的输出,而不是一起输出。
- #include <stdio.h>
- #include <unistd.h> //to use sleep()
- int main(void)
- {
- int i=;
- char buf[]={};
- /*setvbuf(stdout, NULL, _IONBF ,0);*/
- /*setvbuf(stdout, buf , _IOLBF , 1);*/
- for(i=;i<;i++)
- {
- printf("%d ",i);
- fflush(stdout);
- sleep(); //为了查看效果,才加上sleep();
- }
- printf("\n");
- return ;
- }
[root@localhost cpfile]# ./a.out main.c cpfile.c
(null) exist,do you want to overwrite it?(y/n):n
- #include <stdio.h>
- int main(void)
- {
- char ch;
- char ch_1;
- char buf[];
- char buf_1[];
- scanf("%c%s",&ch,buf);
- printf("c=%c, str=%s\n",ch,buf);
- scanf("%c%s",&ch_1,buf_1);
- printf("c=%c, str=%s\n",ch_1,buf_1);
- return ;
- }
- [root@localhost stdio]# vim scanf.c
- [root@localhost stdio]# gcc scanf.c
- [root@localhost stdio]# ./a.out
- hello world //输入 hello world 然后按下回车键
- c=h, str=ello
- c= , str=world
- #include <stdio.h>
- int main(void)
- {
- char ch;
- char ch_1;
- char buf[];
- char buf_1[];
- scanf("%c%s",&ch,buf);
- printf("c=%c, str=%s\n",ch,buf);
- fflush(stdin);
- scanf("%c%s",&ch_1,buf_1);
- printf("c=%c, str=%s\n",ch_1,buf_1);
- return ;
- }
[root@localhost stdio]# ./a.out
hello wolrd
c=h, str=ello
c= , str=wolrd //输出结果为没有将输入数据缓冲区刷出
- FOPEN() Linux Programmer’s Manual FOPEN()
- NAME
- fopen, fdopen, freopen - stream open functions
- SYNOPSIS
- #include <stdio.h>
- FILE *fopen(const char *path, //要打开的文件
- const char *mode); //打开模式
- FILE *fdopen(int fildes, //已经用 open打开的文件的文件描述符
- const char *mode); //打开模式,必须与open的模式兼容
- // 下面的函数,将 stream 文件流重定向到 重新为 path 打开的文件流
- FILE *freopen(const char *path,
- const char *mode,
- FILE *stream);
- FCLOSE() Linux Programmer’s Manual FCLOSE()
- NAME
- fclose - close a stream
- SYNOPSIS
- #include <stdio.h>
- int fclose(FILE *fp);
- FREAD() Linux Programmer’s Manual FREAD()
- NAME
- fread, fwrite - binary stream input/output
- SYNOPSIS
- #include <stdio.h>
- size_t fread(void *ptr, //存储读入数据的数据缓冲区首地址、指针
- size_t size, //要读取的数据块的带小
- size_t nmemb, //每次读取多少个数据块
- FILE *stream); //要读取的文件流
- size_t fwrite(const void *ptr, //存储待写入数据的数据缓冲区首地址、指针
- size_t size, //要写入到数据块的大小
- size_t nmemb, //每次要写入多少个数据块
- FILE *stream); //要写入的文件流
- FERROR() Linux Programmer’s Manual FERROR()
- NAME
- clearerr, feof, ferror, fileno - check and reset stream status
- SYNOPSIS
- #include <stdio.h>
- void clearerr(FILE *stream);
- int feof(FILE *stream); //检测是否到文件尾
- int ferror(FILE *stream);
- int fileno(FILE *stream);
- FSEEK() Linux Programmer’s Manual FSEEK()
- NAME
- fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream
- SYNOPSIS
- #include <stdio.h>
- int fseek(FILE *stream, long offset, int whence);
- long ftell(FILE *stream);
- void rewind(FILE *stream);
- int fgetpos(FILE *stream, fpos_t *pos);
- int fsetpos(FILE *stream, fpos_t *pos);
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define BUF_SIZE 512
- int main(int argc, char* argv[])
- {
- char buf[BUF_SIZE]={};
- FILE* fp_src;
- FILE* fp_dst;
- if(argc<)
- {
- printf("usage: cpfile file_src file_dst\n");
- puts("\t file_src: the source file");
- puts("\t file_dst: the target file");
- exit();
- }
- fp_src = fopen( argv[], "r");
- fp_dst = fopen( argv[], "w");
- while( !feof(fp_src) )
- {
- memset(buf, , sizeof(buf));
- fread(buf, BUF_SIZE, , fp_src);
- fwrite(buf, BUF_SIZE, , fp_dst);
- }
- fclose(fp_src);
- fclose(fp_dst);
- return ;
- }
执行的时候,可以成功复制文件。
【linux草鞋应用编程系列】_1_ 开篇_系统调用IO接口与标准IO接口的更多相关文章
- 【linux草鞋应用编程系列】_2_ 环境变量和进程控制
一. 环境变量 应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作. 在linux中有两种方法获取环境变量,分述如下. 1.通过main函数的参数获取环境变量 ...
- 【linux草鞋应用编程系列】_6_ 重定向和VT100编程
一.文件重定向 我们知道在linux shell 编程的时候,可以使用文件重定向功能,如下所示: [root@localhost pipe]# echo "hello world&q ...
- 【linux草鞋应用编程系列】_5_ Linux网络编程
一.网络通信简介 第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章. 二.linux网络通信 在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...
- 【linux草鞋应用编程系列】_4_ 应用程序多线程
一.应用程序多线程 当一个计算机上具有多个CPU核心的时候,每个CPU核心都可以执行代码,此时如果使用单线程,那么这个线程只能在一个 CPU上运行,那么其他的CPU核心就处于空闲状态,浪费了系 ...
- 【linux草鞋应用编程系列】_3_ 进程间通信
一.进程间通信 linux下面提供了多种进程间通信的方法, 管道.信号.信号量.消息队列.共享内存.套接字等.下面我们分别 介绍管道.信号量.消息队列.共享内存. 信号和套 ...
- 第3章 文件I/O(8)_贯穿案例:构建标准IO函数库
9. 贯穿案例:构建标准IO函数库 //mstdio.h #ifndef __MSTDIO_H__ #define __MSTDIO_H__ #include <unistd.h> #de ...
- linux标准io的copy
---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...
- Linux C++ 网络编程学习系列(1)——端口复用实现
Linux C++ 网络编程学习系列(1)--端口复用实现 源码地址:https://github.com/whuwzp/linuxc/tree/master/portreuse 源码说明: serv ...
- linux makefile: c++ 编程_基础入门_如何开始?
学习android 终究还是需要研究一下其底层框架,所以,学习c++很有必要. 这篇博客,算是linux(ubuntu) 下学习 c++ 的一个入门. 刚开始学习编程语言的时候,最好还是使用命令行操作 ...
随机推荐
- 浅析UPnP协议
摘要:文章介绍了UPnP结构规范和开发流程,指出:UP nP协议使所有联网的设备实现互联,设备工作不需要传统的驱动程序,便可以实现设备间的 相互控制. 关键词:UPnP协议:开发流程:电子技术:工作 ...
- JavaScript中的百变大咖~this
原文链接:http://www.jeffjade.com/2015/08/03/2015-08-03-javascript-this/ JavaScript作为一种脚本语言身份的存在,因此被很多人认为 ...
- vue.js组件化开发实践
前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...
- Form authentication(表单认证)问题
前言 最近在做ASP.NET MVC中表单认证时出了一些问题,特此记录. 问题 进行表单认证时,在 PostAuthenticateRequest 事件中从Cookie值中解密票据.如下: prote ...
- 交叉验证(Cross Validation)原理小结
交叉验证是在机器学习建立模型和验证模型参数时常用的办法.交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏. ...
- 使用Windows EFS(怎么给文件夹加密)进行文件加密
和Windows BitLocker一样,Encrypting File System(EFS,加密文件系统)是Windows内置的一套基于公共密钥的加密机制,可以加密NTFS分区上的文件和文件夹,能 ...
- 如何用 js 获取table 或者其他块状标签的 宽和高
这个比较简单,总体思想,标签标记一个id,js获取id,就能用它的属性了.介绍两种方法.请看下面代码. 第一种 <script> function width_table_all() { ...
- MySQL入门02-MySQL二进制版本快速部署
在上篇文章 MySQL入门01-MySQL源码安装 中,我们介绍了MySQL源码安装的方法. 源码安装虽然有着更加灵活和更加优化等诸多优势.但源码编译安装部署的过程相对复杂,而且整个过程所花费的时间很 ...
- ssh整合问题总结--在添加商品模块实现图片(文件)的上传
今天在做毕设(基于SSH的网上商城项目)中碰到了一个文件上传的需求,就是在后台管理员的商品模块中,有一个添加商品,需要将磁盘上的图片上传到tomcat保存图片的指定目录中: 完成这个功能需要两个步,第 ...
- lamp 环境搭建
LAMP指的Linux(操作系统).ApacheHTTP 服务器,MySQL(数据库软件)和PHP语言 使用wampserver软件,搭建环境.如下图: 双击程序包,安装最后一步随便选择一个浏览器打开 ...