How to traverse the directory under Linux and Windows and how to achieve a consistent operation

Source: Internet
Author: User
Tags exit printf

Recently because of testing purposes to traverse a directory of all the files under the operation, mainly read the contents of each file, as long as you know the filename OK. It can be done directly in Java with the file class, because the combination pattern is used in Java, making it very convenient for clients to use a single file and folder in a consistent way. But it's not the same in C, and there are different ways to use it on different platforms. It is very convenient to implement this function in Linux, because with the API library, several functions are handy (although some small problems, said later), in the implementation of Windows is not so convenient, although also has its own API, but the use of some obscure, because there is no encapsulation, Need to do it step by step, because the Windows API library functions, so if not familiar with the Windows programming, copying the code on the Internet is not easy to debug. To do this, I encapsulate these operations in a Linux-like library function, simplifying transparent operations on the one hand, or, perhaps more importantly, porting, so that the program that contains the feature is ported from Windows to Linux without changing the code (deleting the file that implements the package, Because of Linux, of course, porting from Linux to Windows is also convenient (increase the implementation of the package can be), this is the so-called OCP principle (open closure principle, specific see: Programmers should have the artistic temperament-solid principle). OK, first look at how Linux is doing this function.
The method of traversing directory under Linux

Linux implements directory operations in the API functions are in the header file Dirent.h, the Intercept part of the file contents are as follows:

/** structure describing an open directory.          * * typedef struct _DIRDESC {int dd_fd;        /** file descriptor associated with directory */long Dd_loc;       /** offset in Current buffer */long dd_size;       /** amount of data returned by getdirentries/char *dd_buf;         /** Data buffer */int dd_len;       /** size of data buffer */long dd_seek;     /** Magic Cookie returned by Getdirentries */long dd_rewind;       /** Magic Cookie for rewinding */int dd_flags;    /** flags for Readdir * * struct Pthread_mutex *dd_lock;    /** lock */struct _telldir *dd_td;
    
/** Telldir Position Recording * * DIR;
    
typedef void * DIR;
DIR *opendir (const char *);
DIR *fdopendir (int);
struct Dirent *readdir (DIR *);
void Seekdir (DIR *, long);
Long Telldir (DIR *);
void Rewinddir (DIR *);
    
    
int Closedir (DIR *);              struct Dirent {long D_ino;
 /* Inode number*/    off_t D_off; /* Offset to this dirent*/unsigned short d_reclen;    /* Length of this d_name*/unsigned char d_type;          /* The type of d_name*/char d_name[1]; /* File name (null-terminated) */};

The key part is the definition of the structure of Dir, including the file descriptor, buffer offset, size, buffer content, etc., the following definition is the specific directory operation function, there are open directories, read directories, reset read location, close directory, etc., all I need here is to open, read and close these three basic directory operations , here are examples of use:

#include <stdio.h> 
#include <stdlib.h>    
#include <string.h>  
#include <dirent.h> 
    
#define MAX_LEN 65535
    
int main (void) 
{ 
    DIR *dir; 
    struct dirent *ptr; 
    Char *flow[max_len];
    int num = 0, i = 0;
       
    if ((Dir=opendir ("./data")) = = NULL) 
    { 
        perror ("Open dir error ..."); 
        Exit (1);        
    } 
    Readdir () Return next enter Point's directory dir while
    (Ptr=readdir (dir)!= NULL) 
    { 
        flow[num++] = pt r->d_name;      printf ("%s\n", Flow[num-1]); 
    
    for (i = 0; i < num i++)
    {
        printf ("%s\n", Flow[i]);
       
    Closedir (dir); 

The results of the operation are as follows:

A look at this result is not right, the output is the same file name (the last file filename), where the problem? Print in code/printf ("%s\n", flow[num-1]); This line of comments is removed and then run, and it is found that the annotation is outputting the correct one, both of which are output flow array elements. Debug Discovery is flow[num++] = ptr->d_name; This code problem, because this is a reference copy (address copy), all flow elements all point to the same object Ptr->d_name, although Ptr->d_ The name object is different each time (that is, the reason for the previous correct output), but all of the content shares an address, with a simple diagram to illustrate the following:

Of course, this problem is also relatively easy to solve, but also a more common problem, with a string copy or memory copy on the line, to the flow of each element to reapply a piece of memory.

#include <stdio.h> 
#include <stdlib.h>    
#include <string.h>  
#include <dirent.h> 
    
#define MAX_LEN 65535
    
int main (void) 
{ 
    DIR *dir; 
    struct dirent *ptr; 
    Char *flow[max_len];
    int num = 0, i = 0;
       
    if ((Dir=opendir ("./data")) = = NULL) 
    { 
        perror ("Open dir error ..."); 
        Exit (1);        
    } 
    Readdir () return next to enter Point's directory dir while
    (Ptr=readdir (dir)!= NULL) 
    { 
        Flow[num] = (cha r*) malloc (sizeof (char));
        strcpy (Flow[num], ptr->d_name);
        num++;
    } 
    
    for (i = 0; i < num i++)
    {
        printf ("%s\n", Flow[i]);
       
    Closedir (dir); 

The end result is right.

Second, the method of traversing directory under Windows

Under Windows is more trouble, to use the functions are in Windows.h, Windows programming is more cumbersome, the following is not a description of the use of the function, directly give the package process.

1. First simulate Linux with the header file Dirent.h

The difference is that dir removes some unwanted attributes and defines only three actions that I need to define (on demand).

Dirent.h
#ifndef _sys_dirent_h
#define _SYS_DIRENT_H
    
typedef struct _DIRDESC {
    int     dd_fd;      /** file descriptor associated with directory *    /long dd_loc;     /** offset in current buffer *    /long dd_size;    /** amount of data returned by Getdirentries
    /char    *dd_buf;    /** Data buffer *     /int dd_len;     /** size of data buffer *    /long Dd_seek;    /** Magic Cookie returned by Getdirentries
/} DIR;
    
# define __DIRFD (DP)    (DP)->dd_fd)
    
DIR *opendir (const char *);
struct Dirent *readdir (DIR *);
void Rewinddir (DIR *);
int Closedir (DIR *);
    
#include <sys/types.h>
    
struct dirent
{
     long D_ino;              /* inode number*/
     off_t d_off;             /* Offset to-dirent*/
     unsigned short d_reclen/* length of this
     d_name*/unsigned char d_type;    /* The type of d_name*/
     char d_name[1];          /* File name (null-terminated) */
};
    
#endif

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.