日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Java实现opendir的api_linux文件操作API

發(fā)布時間:2023/12/20 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java实现opendir的api_linux文件操作API 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

from http://blog.chinaunix.net/uid-21411227-id-1826945.html

2010.11

1.Linux文件系統(tǒng)Linux支持多種文件系統(tǒng),如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。在這些具體文件系統(tǒng)的上層,Linux提供了虛擬文件系統(tǒng)(VFS)來統(tǒng)一它們的行為,虛擬文件系統(tǒng)為不同的文件系統(tǒng)與內(nèi)核的通信提供了一致的接口。

在Linux平臺下對文件編程可以使用兩類函數(shù):(1)Linux操作系統(tǒng)文件API;(2)C語言I/O庫函數(shù)。 前者依賴于Linux系統(tǒng)調(diào)用,后者實際上與操作系統(tǒng)是獨立的,因為在任何操作系統(tǒng)下,使用C語言I/O庫函數(shù)操作文件的方法都是相同的。

2.Linux文件API

Linux的文件操作API涉及到創(chuàng)建、打開、讀寫和關(guān)閉文件。

創(chuàng)建

int creat(const char *filename, mode_t mode);

參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(mode&umask),其中umask代表了文件在創(chuàng)建時需要去掉的一些存取權(quán)限。umask可通過系統(tǒng)調(diào)用umask()來改變:

int umask(int newmask);

該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫和執(zhí)行權(quán)限。

打開

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode);

open函數(shù)有兩個形式,其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認為在當前路徑下面),flags可以是下面的一個值或者是幾個值的組合:

標志

含義

O_RDONLY

以只讀的方式打開文件

O_WRONLY

以只寫的方式打開文件

O_RDWR

以讀寫的方式打開文件

O_APPEND

以追加的方式打開文件

O_CREAT

創(chuàng)建一個文件

O_EXEC

如果使用了O_CREAT而且文件已經(jīng)存在,

就會發(fā)生一個錯誤

O_NOBLOCK

以非阻塞的方式打開一個文件

O_TRUNC

如果文件已經(jīng)存在,則刪除文件的內(nèi)容

O_RDONLY、O_WRONLY、O_RDWR三個標志只能使用任意的一個。如果使用了O_CREATE標志,則使用的函數(shù)是int open(const char *pathname,int flags,mode_t mode);這個時候我們還要指定mode標志,用來表示文件的訪問權(quán)限。mode可以是以下情況的組合:

標志

含義

S_IRUSR

用戶可以讀

S_IWUSR

用戶可以寫

S_IXUSR

用戶可以執(zhí)行

S_IRWXU

用戶可以讀、寫、執(zhí)行

S_IRGRP

組可以讀

S_IWGRP

組可以寫

S_IXGRP

組可以執(zhí)行

S_IRWXG

組可以讀寫執(zhí)行

S_IROTH

其他人可以讀

S_IWOTH

其他人可以寫

S_IXOTH

其他人可以執(zhí)行

S_IRWXO

其他人可以讀、寫、執(zhí)行

S_ISUID

設(shè)置用戶執(zhí)行ID

S_ISGID

設(shè)置組的執(zhí)行ID

除了可以通過上述宏進行“或”邏輯產(chǎn)生標志以外,我們也可以自己用數(shù)字來表示,Linux總共用5個數(shù)字來表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID;第二位表示設(shè)置組ID;第三位表示用戶自己的權(quán)限位;第四位表示組的權(quán)限;最后一位表示其他人的權(quán)限。每個數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫權(quán)限)、4(讀權(quán)限)、0(無)或者是這些值的和。例如,要創(chuàng)建一個用戶可讀、可寫、可執(zhí)行,但是組沒有權(quán)限,其他人可以讀、可以執(zhí)行的文件,并設(shè)置用戶ID位。那么,我們應(yīng)該使用的模式是1(設(shè)置用戶ID)、0(不設(shè)置組ID)、7(1+2+4,讀、寫、執(zhí)行)、0(沒有權(quán)限)、5(1+4,讀、執(zhí)行)即10705:

open("test", O_CREAT, 10705);

上述語句等價于:

open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID );

如果文件打開成功,open函數(shù)會返回一個文件描述符,以后對該文件的所有操作就可以通過對這個文件描述符進行操作來實現(xiàn)。讀寫

在文件打開以后,我們才可對文件進行讀寫了,Linux中提供文件讀寫的系統(tǒng)調(diào)用是read、write函數(shù):

int read(int fd, const void *buf, size_t length);

int write(int fd, const void *buf, size_t length);

其中參數(shù)buf為指向緩沖區(qū)的指針,length為緩沖區(qū)的大小(以字節(jié)為單位)。函數(shù)read()實現(xiàn)從文件描述符fd所指定的文件中讀取length個字節(jié)到buf所指向的緩沖區(qū)中,返回值為實際讀取的字節(jié)數(shù)。函數(shù)write實現(xiàn)將把length個字節(jié)從buf指向的緩沖區(qū)中寫到文件描述符fd所指向的文件中,返回值為實際寫入的字節(jié)數(shù)。  以O(shè)_CREAT為標志的open實際上實現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù):

int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);

定位

對于隨機文件,我們可以隨機的指定位置讀寫,使用如下函數(shù)進行定位:

int lseek(int fd, offset_t offset, int whence);

lseek()將文件讀寫指針相對whence移動offset個字節(jié)。操作成功時,返回文件指針相對于文件頭的位置。參數(shù)whence可使用下述值:  SEEK_SET:相對文件開頭  SEEK_CUR:相對文件讀寫指針的當前位置  SEEK_END:相對文件末尾  offset可取負值,例如下述調(diào)用可將文件指針相對當前位置向前移動5個字節(jié):

lseek(fd, -5, SEEK_CUR);

由于lseek函數(shù)的返回值為文件指針相對于文件頭的位置,因此下列調(diào)用的返回值就是文件的長度:

lseek(fd, 0, SEEK_END);

關(guān)閉

當我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符:

int close(int fd);

下面我們學(xué)習(xí)一個實例,這個實例用來拷貝文件.

#include

#define BUFFER_SIZE 1024

int main(int argc,char **argv)

{

int from_fd,to_fd;

int bytes_read,bytes_write;

char buffer[BUFFER_SIZE];

char *ptr;

if(argc!=3)

{

fprintf(stderr,"Usage:%s fromfile tofile\n\a",argv[0]);

exit(1);

}

/*打開源文件*/

if((from_fd=open(argv[1],O_RDONLY))==-1)

{

fprintf(stderr,"Open %s Error:%s\n",argv[1],strerror(errno));

exit(1);

}

/*創(chuàng)建目的文件*/

if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)

{

fprintf(stderr,"Open %s Error:%s\n",argv[2],strerror(errno));

exit(1);

}

/*以下代碼是一個經(jīng)典的拷貝文件的代碼*/

while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))

{

/*一個致命的錯誤發(fā)生了*/

if((bytes_read==-1)&&(errno!=EINTR)) break;

else if(bytes_read>0)

{

ptr=buffer;

while(bytes_write=write(to_fd,ptr,bytes_read))

{

/*一個致命錯誤發(fā)生了*/

if((bytes_write==-1)&&(errno!=EINTR))break;

/*寫完了所有讀的字節(jié)*/

else if(bytes_write==bytes_read) break;

/*只寫了一部分,繼續(xù)寫*/

else if(bytes_write>0)

{

ptr+=bytes_write;

bytes_read-=bytes_write;

}

}

/*寫的時候發(fā)生的致命錯誤*/

if(bytes_write==-1)break;

}

}

close(from_fd);

close(to_fd);

exit(0);

}

3:文件的各個屬性

文件具有各種各樣的屬性,除了我們上面所知道的文件權(quán)限以外,文件還有創(chuàng)建時間,大小等等屬性.

有時侯我們要判斷文件是否可以進行某種操作(讀,寫等等).這個時候我們可以使用access函數(shù).

#include

int access(const char *pathname,int mode);

pathname:是文件名稱,mode是我們要判斷的屬性.可以取以下值或者是他們的組合.

R_OK文件可以讀,W_OK文件可以寫,X_OK文件可以執(zhí)行,F_OK文件存在.當我們測試成功時,函數(shù)返回0,否則如果有一個條件不符時,返回-1.

如果我們要獲得文件的其他屬性,我們可以使用函數(shù)stat或者fstat.

#include

#include

int stat(const char *file_name,struct stat *buf);

int fstat(int filedes,struct stat *buf);

struct stat {

dev_t st_dev; /*設(shè)備*/

ino_t st_ino; /*節(jié)點*/

mode_t st_mode; /*模式*/

nlink_t st_nlink; /*硬連接*/

uid_t st_uid; /*用戶ID */

gid_t st_gid; /*組ID */

dev_t st_rdev; /*設(shè)備類型*/

off_t st_off; /*文件字節(jié)數(shù)*/

unsigned long st_blksize; /*塊大小*/

unsigned long st_blocks; /*塊數(shù)*/

time_t st_atime; /*最后一次訪問時間*/

time_t st_mtime; /*最后一次修改時間*/

time_t st_ctime; /*最后一次改變時間(指屬性) */

};

stat用來判斷沒有打開的文件,而fstat用來判斷打開的文件.我們使用最多的屬性是st_mode.通過著屬性我們可以判斷給定的文件是一個普通文件還是一個目錄,連接等等.可以使用下面幾個宏來判斷.

S_ISLNK(st_mode):是否是一個連接.S_ISREG是否是一個常規(guī)文件.S_ISDIR是否是一個目錄S_ISCHR是否是一個字符設(shè)備.S_ISBLK是否是一個塊設(shè)備S_ISFIFO是否是一個FIFO文件.S_ISSOCK是否是一個SOCKET文件.

4:目錄文件的操作

在我們編寫程序的時候,有時候會要得到我們當前的工作路徑。C庫函數(shù)提供了getcwd來解決這個問題。

#include

char *getcwd(char *buffer,size_t size);

我們提供一個size大小的buffer,getcwd會把我們當前的路徑考到buffer中.如果buffer太小,函數(shù)會返回-1和一個錯誤號.

Linux提供了大量的目錄操作函數(shù),我們學(xué)習(xí)幾個比較簡單和常用的函數(shù).

#include

int mkdir(const char *path,mode_t mode);

DIR *opendir(const char *path);

struct dirent *readdir(DIR *dir);

void rewinddir(DIR *dir);

off_t telldir(DIR *dir);

void seekdir(DIR *dir,off_t off);

int closedir(DIR *dir);

struct dirent {

long d_ino;

off_t d_off;

unsigned short d_reclen;

char d_name[NAME_MAX+1]; /*文件名稱*/

mkdir很容易就是我們創(chuàng)建一個目錄,opendir打開一個目錄為以后讀做準備.readdir讀一個打開的目錄.rewinddir是用來重讀目錄的和我們學(xué)的rewind函數(shù)一樣.closedir是關(guān)閉一個目錄.telldir和seekdir類似與ftee和fseek函數(shù).

下面我們開發(fā)一個小程序,這個程序有一個參數(shù).如果這個參數(shù)是一個文件名,我們輸出這個文件的大小和最后修改的時間,如果是一個目錄我們輸出這個目錄下所有文件的大小和修改時間.

#include

static int get_file_size_time(const char *filename)

{

struct stat statbuf;

if(stat(filename,&statbuf)==-1)

{

printf("Get stat on %s Error:%s\n",

filename,strerror(errno));

return(-1);

}

if(S_ISDIR(statbuf.st_mode))return(1);

if(S_ISREG(statbuf.st_mode))

printf("%s size:%ld bytes\tmodified at %s",

filename,statbuf.st_size,ctime(&statbuf.st_mtime));

return(0);

}

int main(int argc,char **argv)

{

DIR *dirp;

struct dirent *direntp;

int stats;

if(argc!=2)

{

printf("Usage:%s filename\n\a",argv[0]);

exit(1);

}

if(((stats=get_file_size_time(argv[1]))==0)||(stats==-1))exit(1);

if((dirp=opendir(argv[1]))==NULL)

{

printf("Open Directory %s Error:%s\n",

argv[1],strerror(errno));

exit(1);

}

while((direntp=readdir(dirp))!=NULL)

if(get_file_size_time(direntp-br> closedir(dirp);

exit(1);

}

5:管道文件

Linux提供了許多的過濾和重定向程序,比如more cat

等等.還提供了< > | <

#include

int pipe(int fildes[2]);

pipe調(diào)用可以創(chuàng)建一個管道(通信緩沖區(qū)).當調(diào)用成功時,我們可以訪問文件描述符fildes[0],fildes[1].其中fildes[0]是用來讀的文件描述符,而fildes[1]是用來寫的文件描述符.

在實際使用中我們是通過創(chuàng)建一個子進程,然后一個進程寫,一個進程讀來使用的.

#include

#define BUFFER 255

int main(int argc,char **argv)

{

char buffer[BUFFER+1];

int fd[2];

if(argc!=2)

{

fprintf(stderr,"Usage:%s string\n\a",argv[0]);

exit(1);

}

if(pipe(fd)!=0)

{

fprintf(stderr,"Pipe Error:%s\n\a",strerror(errno));

exit(1);

}

if(fork()==0)

{

close(fd[0]);

printf("Child[%d] Write to pipe\n\a",getpid());

snprintf(buffer,BUFFER,"%s",argv[1]);

write(fd[1],buffer,strlen(buffer));

printf("Child[%d] Quit\n\a",getpid());

exit(0);

}

else

{

close(fd[1]);

printf("Parent[%d] Read from pipe\n\a",getpid());

memset(buffer,'\0',BUFFER+1);

read(fd[0],buffer,BUFFER);

printf("Parent[%d] Read:%s\n",getpid(),buffer);

exit(1);

}

}

為了實現(xiàn)重定向操作,我們需要調(diào)用另外一個函數(shù)dup2.

#include

int dup2(int oldfd,int newfd);

dup2將用oldfd文件描述符來代替newfd文件描述符,同時關(guān)閉newfd文件描述符.也就是說,所有向newfd操作都轉(zhuǎn)到oldfd上面.下面我們學(xué)習(xí)一個例子,這個例子將標準輸出重定向到一個文件.

#include

#define BUFFER_SIZE 1024

int main(int argc,char **argv)

{

int fd;

char buffer[BUFFER_SIZE];

if(argc!=2)

{

fprintf(stderr,"Usage:%s outfilename\n\a",argv[0]);

exit(1);

}

if((fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)

{

fprintf(stderr,"Open %s Error:%s\n\a",argv[1],strerror(errno));

exit(1);

}

if(dup2(fd,STDOUT_FILENO)==-1)

{

fprintf(stderr,"Redirect Standard Out Error:%s\n\a",strerror(errno));

exit(1);

}

fprintf(stderr,"Now,please input string");

fprintf(stderr,"(To quit use CTRL+D)\n");

while(1)

{

fgets(buffer,BUFFER_SIZE,stdin);

if(feof(stdin))break;

write(STDOUT_FILENO,buffer,strlen(buffer));

}

exit(0);

}

總結(jié)

以上是生活随笔為你收集整理的Java实现opendir的api_linux文件操作API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。