····要编写ls命令,首先要了解它能做什么,完成了什么工作,是如何完成这些工作的····


 一、ls命令能做什么?

  我们在命令行输入ls,ls默认找出当前目录中所有文件的文件名,并且按照字典序排序后输出。ls命令有很多参数选项,可以决定ls的输出内容。如果参数是目录,ls列出目录的内容,如果参数是文件,ls列出文件名和属性。
  例如:ls -l
       (每行7个字段,mode+links+owers+group+size+last-modified+name)

  问题在于:

    1.如何列出目录的内容。

    2.如何读取并显示文件的属性。

    3.给出一个名字,如何判断出它是目录还是文件。


二、ls命令是如何工作的?

  文件和目录被组成一棵目录树结构。目录是一种特殊的文件,其内容是文件和目录的名字。目录是记录的序列,每条记录对应一个文件或子目录,通过readdir来读取目录中的记录,readdir返回一个指向目录的当前记录的指针,记录的类型是struct_dirent。


三、如何编写ls命令?

  框架:
    mian()
    opendir
    while(readdir)
      print d_name
    closedir


几个结构体的解析:

1、结构体__dirstream:

struct __dirstream{
         void* __fd;
         char* __data;
         int __entry_data;
         char* __ptr;
         int __entry_ptr;
         size_t __allocation;
         size_t __size;
         __libc_lock_define(,__lock)
};
typedef struct __dirstream DIR;

  DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息。
  Eg: DIR *opendir(const char *parhname);打开文件目录,返回指向DIR 结构体的指针。
     struct dirent *readdir(DIR *dp);
     void rewinddir(DIR *dp);
     int closedir(DIR *dp);
     long telldir(DIR *dp);
     void seekdir(DIR *dp,long loc);

2、结构体 dirent:

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; not supported by all file system types文件类型 */
      char d_name[]; /* filename 文件名,最长255字符*/
};

  目录文件(directory file):这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针。从此可以看出,dirent不仅仅指向目录,还指向目录中的具体文件。(readdir函数同样也可以读取目录下的文件,这就是证据)
  从上述的定义我们可以看出dirent结构体中存储的有关文件的信息太少,不能满足我们的需求,即dirent只是起到了索引的作用。所以我们要想获得ls -l类似的信息,必须通过stat函数获取。
通过readdir函数读取到文件名并存储到结构体dirent的d_name成员中,然后通过int stat(const *file_name,struct stat *buf)获取文件名为d_name的文件的详细信息,并存储在stat结构体中。

3、结构体 stat:

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 所有者用户识别号*/
     gid_t st_gid; /* group ID of owner 组识别号*/
     dev_t st_rdev; /* device ID (if special file) 设备文件的设备号*/
     off_t st_size; /* total size, in bytes 以字节为单位的文件容量*/
     blksize_t st_blksize; /* blocksize for file system I/O 包含该文件的磁盘块的大小*/
     blkcnt_t st_blocks; /* number of 512B 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 最后一次改变文件状态的时间*/
};

 struct stat中的st_mode值各个位代表的含义:

The following flags are defined for the st_mode field:
      /* 是什么类型的文件 */
S_IFMT bit mask for the file type bit fields
S_IFSOCK socket
S_IFLNK symbolic link
S_IFREG regular file
S_IFBLK block device
S_IFDIR directory
S_IFCHR character device
S_IFIFO FIFO
S_ISUID set UID bit
S_ISGID set-group-ID bit (see below)
S_ISVTX sticky bit (see below)
      /* 是否有可读写权限 */
S_IRWXU mask for file owner permissions
S_IRUSR owner has read permission
S_IWUSR owner has write permission
S_IXUSR owner has execute permission
S_IRWXG mask for group permissions
S_IRGRP group has read permission
S_IWGRP group has write permission
S_IXGRP group has execute permission
S_IRWXO mask for permissions for others (not in group)
S_IROTH others have read permission
S_IWOTH others have write permission
S_IXOTH others have execute permission

4、结构体passwd :

/* The passwd structure.  */
struct passwd
{
char *pw_name; /* Username. */
char *pw_passwd; /* Password. */
__uid_t pw_uid; /* User ID. */
__gid_t pw_gid; /* Group ID. */
char *pw_gecos; /* Real name. */
char *pw_dir; /* Home directory. */
char *pw_shell; /* Shell program. */
};

5、结构体group:

/* The group structure.     */
struct group
{
char *gr_name; /* Group name. */
char *gr_passwd; /* Password. */
__gid_t gr_gid; /* Group ID. */
char **gr_mem; /* Member list. */
};

6、结构体tm:

/* Used by other time functions.  */
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/ #ifdef __USE_BSD
long int tm_gmtoff; /* Seconds east of UTC. */
__const char *tm_zone; /* Timezone abbreviation. */
#else
long int __tm_gmtoff; /* Seconds east of UTC. */
__const char *__tm_zone; /* Timezone abbreviation. */
#endif
};

sunmmary:

如果想获取某目录下(eg:目录a)b文件的详细信息,我们该怎么做?
  1、使用opendir函数打开目录a,返回指向目录a的DIR的结构体c。
  2、调用readdir(c)函数读取目录a下所有的文件(包括目录),返回指向目录a下所有文件的dirent结构体d。
  3、遍历d,调用stat(d->name,stat *e)函数来获取每个文件的详细信息,并存储在stat结构体e中。


知识点解释:

1、stat得到文件属性:
    int result = stat(char * fname , struct stat * bufp)
    包含在# include <sys/stat.h>,把文件fname的信息复制到指针bufp所指的结构中。

2、将mode模式字段转换成字符:
    st_mode是一个16位的二进制数,文件类型和权限被编码在这个数中。
    字段编码——整数是bit组成的序列,使用八进制简化表示。
    解码——掩码技术(与0做位于)。

3、将用户/组ID转换成字符串:
    etc/passwd文件中包含用户列表(搜索文件繁琐),而且其并没有包含所有的用户(网络计算系统,所有主机通过NIS进行用户身份验证)。
    通过getpwuid来得到完整的用户列表——通过库函数getpwuid来访问用户信息,如果用户信息保存在/etc/passwd中,那么getpwuid就会查找/etc/passwd的内容,如果用户信息在NIS中,getpwuid会从NIS中获取信息。
    getpwuid需要uid作为参数,返回一个指向struct passwd的指针。
    return getpwuid(uid)->pw_name
同理:/etc/group是组列表,通过getgrgid访问组列表。

4、用ctime将time_t类型的修改时间转换成字符串格式:
    char *ctime(const time_t *time);包含于time.h中

5、参数(目录OR某个文件)判断:
    if((st.st_mode & S_IFMT) == S_IFDIR)成立则是目录。

6、排序后输出:
    qsort()函数使用快速排序的例程进行排序,包含于stdlib.h中。
    void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));
    参数解析:    *base:待排序数组首地址
          nelem:数组中待排序元素数目
          width:各元素占用的空间大小
          *:指向函数的指针,用于确定排序的顺存

qsort参考链接:http://baike.baidu.com/view/982231.htm?fr=aladdin

7、高亮显示:

文件按照属性显示颜色
        033[mode;foreground;backgroundmhello\033[0m

mode为显示模式:
        0、1、22、4、24、5、25、7、27,分别表示设定颜色、黑体、非黑体、下画线、非下画线、闪烁、非闪烁、翻转、非翻转。

foreground为前景颜色:
        30 (黑色)、31 (红色)、32 (绿色)、33 (黄色)、34 (蓝色)、35 ( 紫红色)、36 (青色)和37 (白色)

background为背景颜色:
        40 (黑色)、41 (红色)、42 (绿色)、43 (黄色)、44 (蓝色)、45 ( 紫红色)、46 (青色)和47 (白色)

 样式:
— Normal (no color, no bold)
— Bold //粗体 文字颜色
— Black //黑色
— Red //红色
— Green //绿色
— Yellow //黄色
— Blue //蓝色
— Magenta //洋红色
— Cyan //蓝绿色
— White //白色 背景颜色
— Black
— Red
— Green
— Yellow
— Blue
— Magenta
— Cyan
– White 白色: 表示普通文件
蓝色: 表示目录
绿色: 表示可执行文件
红色: 表示压缩文件
蓝绿色: 链接文件
红色闪烁:表示链接的文件有问题
黄色: 表示设备文件
灰色: 表示其他文件

ls下高亮显示

8、获取符号链接:

readlink读取符号链接内容:

  表头文件: #include <unistd.h>

  定义函数:ssize_t readlink(const char *path, char *buf, size_t bufsiz);

          path为符号链接路径
          buf为符号链接内容
          bufsize为要获得内容长度

  函数说明:readlink()会将参数path的符号链接内容存储到参数buf所指的内存空间,返回的内容不是以\000作字符串结尾,但会将字符串的字符数返回,这使得添加\000变得简单。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断,如果 readlink 第一个参数指向一个文件而不是符号链接时,readlink 设 置errno 为 EINVAL 并返回 -1。 readlink()函数组合了open()、read()和close()的所有操作。

  返回值 :执行成功则返回字符串的字符数,失败返回-1, 错误代码存于errno
      执行成功则返回ssize_t
  错误代码:
      EACCESS 取文件时被拒绝,权限不够
      EINVAL 参数bufsiz为负数
      EIO O存取错误
      ELOOP 欲打开的文件有过多符号连接问题
      ENAMETOOLONG 参数path的路径名称太长
      ENOENT 参数path所指定的文件不存在
      ENOMEM 核心内存不足
      ENOTDIR 参数path路径中的目录存在但却非真正的目录
      PHP 5. 3.0 后在windows下可实现。

待完成工作:
  1、对于指定目录下信息的显示。
  2、支持参数选项:-R,-u等。



附注:

 /* ls2_3.c
* -r -l
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <grp.h>
#include <pwd.h> void do_ls_ls(char[]); //No para
void do_ls(char[],int); //para
void dostat(char *); //file status
void show_file_info( char *, struct stat *);
void mode_to_letters( int , char [] );
char *uid_to_name( uid_t );
char *gid_to_name( gid_t ); void *emalloc(unsigned),*erealloc(void *, unsigned);
char **namelist = NULL;
int listlen = ;
int taken = ; //设置显示颜色
int background = ;
int foreground = ;
int colormode = ; #define CHUNKLEN 100 main(int ac, char *av[])
{
int r_flag = ;
int anyfile = ; struct stat st; if ( ac == ) //没有参数
{
//检查
printf("hello---ac=1\n\n");
do_ls_ls(".");
printf("hello----ac=1结束\n\n");
}
else
while ( --ac ){
*av++;
if(strcmp("-l",*av) == ) //参数为-l,正序输出
{
r_flag = ;
//检查
printf("hello---参数为l\n\n");
do_ls( "." ,r_flag);
printf("hello---参数为l结束\n\n");
}
else if(strcmp("-r",*av) == ) //参数为-r,倒序输出
{
//检查
printf("hello----参数为r\n\n");
r_flag = ;
do_ls( "." ,r_flag);
printf("hello---参数为r结束\n\n");
}
else if(stat(*av, &st) < )
{
//检查
printf("hello----参数\n\n");
perror("stat");
printf("hello---参数:结束\n\n");
}
else if((st.st_mode & S_IFMT) == S_IFDIR)
{
//检查
printf("hello---参数为目录 \n\n");
display_dir(*av);
printf("hello---参数为目录结束\n\n");
}
else
{
//检查
printf("hello---参数为某个文件\n\n");
dostat(*av);
printf("hello---参数为某个文件结束\n\n");
}
anyfile = ;
}
} void do_ls_ls( char dirname[] )
{
int i;
DIR *dir_ptr; /* the directory */
struct dirent *direntp; /* each entry */ list_init(); if ( ( dir_ptr = opendir( dirname ) ) == NULL )
fprintf(stderr,"ls2: cannot open %s\n", dirname);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
list_append(direntp->d_name);
list_sort();
// printf("%s\n", direntp->d_name );
}
for(i=;i<taken;i++)
printf("%s\n", namelist[i]);
// dostat(namelist[i]);
closedir(dir_ptr);
}
list_finish();
} int display_dir(char *dirname)
{
DIR *dir;
struct dirent *dirent;
struct stat st;
char buf[]; dir = opendir(dirname); //检查
printf("hello---display_dir\n\n");
while((dirent = readdir(dir)) != NULL)
{
strcpy(buf, dirname);
strcat(buf, "/");
strcat(buf, dirent->d_name);
if(stat(buf, &st))
{
perror("stat");
return -;
}
if(dirent->d_name[] != '.')
display_file(buf, dirent->d_name);
}
printf("\nhello---display_dir结束\n\n");
closedir(dir);
} int display_file(char *path, char *filename)
{
struct stat st;
int i;
struct passwd *pw;
struct group *gr;
struct tm *tm;
stat(path, &st);
dostat(filename);
return ;
} list_init()
{
namelist = (char **)emalloc(CHUNKLEN * sizeof(char *));
listlen = CHUNKLEN;
taken = ;
} list_append(char *str)
{
char *newstring(char *);
char *name = newstring(str); if(taken == listlen){
listlen += CHUNKLEN;
namelist = (char **)erealloc(namelist,listlen);
}
namelist[taken++] = name ; } list_finish()
{
int i;
for (i=;i<taken;i++)
free(namelist[i]);
free(namelist);
taken = listlen = ;
} int comp_increasing(char **p1,char **p2)
{
return strcmp((char *) *p1,(char *) *p2);
} int comp_decreasing(char **p1,char **p2)
{
return strcmp((char *) *p2,(char *) *p1);
} list_sort(int revflag)
{
qsort((void *)namelist,(size_t)taken,sizeof(char *),(__compar_fn_t)(revflag?comp_decreasing:comp_increasing)); } void do_ls( char dirname[] , int reverse )
{
int i;
DIR *dir_ptr; /* the directory */
struct dirent *direntp; /* each entry */ list_init(); if ( ( dir_ptr = opendir( dirname ) ) == NULL )
fprintf(stderr,"ls2: cannot open %s\n", dirname);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
list_append(direntp->d_name);
list_sort(reverse);
} for(i=;i<taken;i++)
dostat( namelist[i] ); closedir(dir_ptr);
}
list_finish();
} char *newstring(char *s)
{
char *rv = emalloc(+strlen(s));
strcpy(rv,s);
return rv;
} void *emalloc(unsigned n)
{
void *rv = malloc(n);
if(rv)
return rv;
fprintf(stderr, "ls2:%s/%s\n","out of memory","");
} void *erealloc(void *p,unsigned n)
{
void *rv = realloc(p,n);
if(rv)
return rv;
fprintf(stderr, "ls2:%s/%s\n","out of memory","");
} /*
* 获得文件的属性
*/
void dostat( char *filename )
{
struct stat info; if ( stat(filename, &info) == - ) /* cannot stat */
perror( filename ); /* say why */
else /* else show info */
show_file_info( filename, &info );
} void show_file_info( char *filename, struct stat *info_p )
{
char *uid_to_name(), *ctime(), *gid_to_name(), *filemode();
void mode_to_letters();
char modestr[]; mode_to_letters( info_p->st_mode, modestr); printf( "%7d " , info_p->st_ino ); //i节点号
printf( "%s" , modestr );
printf( "%4d " , (int) info_p->st_nlink);
printf( "%-8s " , uid_to_name(info_p->st_uid) );
printf( "%-8s " , gid_to_name(info_p->st_gid) );
printf( "%8ld " , (long)info_p->st_size);
printf( "%.12s ", +ctime(&info_p->st_mtime));
printf( "\033[%d;%d;%dm%s\033[0m\n" , foreground, background, colormode, filename ); } void mode_to_letters( int mode, char str[])
{
strcpy( str, "----------" ); /* default=no perms */ if ( S_ISDIR(mode) ) {foreground = ; str[] = 'd';} /* directory? */
if ( S_ISCHR(mode) ) {colormode = ; foreground = ; background = ; str[] = 'c';} /* char devices */
if ( S_ISBLK(mode) ) {colormode = ; foreground = ; background = ; str[] = 'b';} /* block device */ if ( mode & S_IRUSR ) str[] = 'r'; /* 3 bits for user */
if ( mode & S_IWUSR ) str[] = 'w';
if ( mode & S_IXUSR ) { if(foreground == ) foreground = ; str[] = 'x';} if ( mode & S_IRGRP ) str[] = 'r'; /* 3 bits for group */
if ( mode & S_IWGRP ) str[] = 'w';
if ( mode & S_IXGRP ) { if(foreground == ) foreground = ; str[] = 'x';} if ( mode & S_IROTH ) str[] = 'r'; /* 3 bits for other */
if ( mode & S_IWOTH ) str[] = 'w';
if ( mode & S_IXOTH ) { if(foreground == ) foreground = ; str[] = 'x';}
} char *uid_to_name( uid_t uid )
{
struct passwd *getpwuid(), *pw_ptr;
static char numstr[]; if ( ( pw_ptr = getpwuid( uid ) ) == NULL ){
sprintf(numstr,"%d", uid);
return numstr;
}
else
return pw_ptr->pw_name ;
} char *gid_to_name( gid_t gid )
{
struct group *getgrgid(), *grp_ptr;
static char numstr[]; if ( ( grp_ptr = getgrgid(gid) ) == NULL ){
sprintf(numstr,"%d", gid);
return numstr;
}
else
return grp_ptr->gr_name;
}

自己代码

 #include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <time.h> int display_file(char *path, char *filename)
{
struct stat st;
int i;
struct passwd *pw;
struct group *gr;
struct tm *tm;
stat(path, &st); switch(st.st_mode & S_IFMT)
{
case S_IFREG: printf("-"); break;
case S_IFDIR: printf("d"); break;
case S_IFLNK: printf("l"); break;
case S_IFBLK: printf("b"); break;
case S_IFCHR: printf("c"); break;
case S_IFIFO: printf("p"); break;
case S_IFSOCK: printf("s"); break;
} for(i = ; i >= ; i--)
{
if(st.st_mode & ( << i))
{
switch(i%)
{
case : printf("r"); break;
case : printf("w"); break;
case : printf("x"); break;
}
}
else
printf("-");
} pw = getpwuid(st.st_uid);
gr = getgrgid(st.st_gid); printf("%2d %s %s %4ld", st.st_nlink, pw->pw_name, gr->gr_name, st.st_size); tm = localtime(&st.st_ctime);
printf(" %04d-%02d-%02d %02d:%02d",tm->tm_year + , tm->tm_mon + , tm->tm_mday, tm->tm_hour, tm->tm_min); printf(" %s\n", filename); return ;
} int display_dir(char *dirname)
{
DIR *dir;
struct dirent *dirent;
struct stat st;
char buf[]; dir = opendir(dirname);
while((dirent = readdir(dir)) != NULL)
{
strcpy(buf, dirname);
strcat(buf, "/");
strcat(buf, dirent->d_name);
if(stat(buf, &st))
{
perror("stat");
return -;
} if(dirent->d_name[] != '.')
display_file(buf, dirent->d_name);
}
} int main(int argc, char **argv)
{
struct stat st;
char buf[]; if(stat(argv[], &st) < )
{
perror("stat");
return -;
} if((st.st_mode & S_IFMT) == S_IFDIR)
display_dir(argv[]);
else
display_file(argv[], argv[]); return ;
}

童鞋代码

链接:

ubuntu 编写自己的ls命令http://www.cnblogs.com/lr-ting/archive/2012/06/19/2555207.html

高亮显示:http://www.embedu.org/Column/Column341.htm

编写自己的ls命令的更多相关文章

  1. Linux系统编程【3.1】——编写ls命令

    ls命令简介 老规矩,直接在终端输入:man ls (有关于man命令的简介可以参考笔者前期博客:Linux系统编程[1]--编写more命令) 可以看到,ls命令的作用是显示目录中的文件名,它带有可 ...

  2. 20145239 Linux下常用的ls命令总结

    20145239 Linux下常用的ls命令总结 通过学习本周的教学视频和要求掌握的内容,发现ls命令被使用的次数非常多,但作为一个初学者,可能我只会ls或者顶多ls -l两种用法.但其实ls是一个非 ...

  3. Linux/UNIX编程:使用C语言实现简单的 ls 命令

    刚好把 Linux/UNIX 编程中的文件和IO部分学完了,就想编写个 ls 命令练习一下,本以为很简单,调用个 stat 就完事了,没想到前前后后弄了七八个小时,90%的时间都用在格式化(像 ls ...

  4. Linux系统编程【3.2】——ls命令优化版和ls -l实现

    前情提要 在笔者的上一篇博客Linux系统编程[3.1]--编写ls命令中,实现了初级版的ls命令,但是与原版ls命令相比,还存在着显示格式和无颜色标记的不同.经过笔者近两天的学习,基本解决了这两个问 ...

  5. 每天一个linux命令(1):ls命令

    1. 命令格式: ls [选项] [目录名] 2. 命令功能: 列出目标目录中所有的子目录和文件. 4. 常用范例: 例一:列出/home/peidachang文件夹下的所有文件和目录的详细资料 命令 ...

  6. Linux 常用命令 :ls命令

    ls命令是linux下最常用的命令.ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linu ...

  7. linux在home目录下使用ls命令卡死

    linux在home目录下使用ls命令卡死,原因可能是mount的某个服务器挂掉或出啥问题了,这个时候umount掉就正常了,如果umount提示device is busy,这时可以使用强制卸载   ...

  8. linux命令(1):ls命令

    ls命令是linux下最常用的命令. ls命令就是list的缩写,缺省下ls用来打印出当前目录的清单,如果ls指定其他目录,那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看lin ...

  9. 《The Linux Command Line》 读书笔记03 ls命令与长格式输出解释 文件权限

    ls命令与长格式输出解释 文件权限 ls命令 ls 命令用于列出目录内容,不带参数时列出当前工作目录的内容,也可以指定目标目录(可以指定多个),列出目标目录下的内容. ls命令的参数 ls -l 长格 ...

随机推荐

  1. Jacoco覆盖率工具使用之maven篇

    说明 之前的文章已经介绍过如何使用apacheant 执行jacoco工具,下面开始介绍如何使用maven使用jacoco工具. 1.首先新建一个maven项目       如图所示:        ...

  2. 微信团队分享:iOS版微信的高性能通用key-value组件技术实践

    本文来自微信开发团队guoling的技术分享. 1.前言 本文要分享的是iOS版微信内部正在推广和使用的一个高性能通用key-value 组件的技术实践过程,该组件在微信内部被命名为MMKV(以下简称 ...

  3. Django——静态文件配置

    本文目的 最近用django开发项目,发现django的静态文件(js,css和img等)配置比较麻烦,开发环境和生产环境的配置还不一样,这里记录一下,作为备忘.我当前使用的版本是django v1. ...

  4. 微信小程序flex容器属性详解

    flex容器属性详解 flex-direction决定元素的排列方向 flex-wrap决定元素如何换行 flex-flow 是 flex-direction 和flex-wrap的简写 justif ...

  5. 模式识别之Earley算法入门详讲

    引言:刚学习模式识别时,读Earley算法有些晦涩,可能是自己太笨.看了网上各种资料,还是似懂非懂,后来明白了,是网上的前辈们境界太高,写的最基本的东西还是非常抽象,我都领悟不了,所以决定写个白痴版的 ...

  6. C语言-EOF和feof()判断文件结尾的区别

    今天获取一个图片内容时, fopen("aaaaaa.png", "r"), 读取完文件头就停止了, 后来模式改为 "rb" 就可以了, 特 ...

  7. 开源静态分析工具androguard体验

    原文链接:http://blog.csdn.net/xbalien29/article/details/21885297 虽然在windows端免费版的IDA.VTS等工具都可用来静态分析,但相对来说 ...

  8. http协议---简述

    http(Hypertext transfer protocol)超文本传输协议,通过浏览器和服务器进行数据交互,进行超文本(文本.图片.视频等)传输的规定. 也就是说,http协议规定了超文本传输所 ...

  9. CSS3 稳固而知新: 居中

    水平居中 transform: translateX(-50%); left: 50%; 垂直居中同理 transform: translateY(-50%);   top:50%;     垂直水平 ...

  10. css3中-moz、-ms、-webkit,-o分别代表的意思

    这种方式在业界上统称:识别码.前缀 //-ms代表[ie]内核识别码 //-moz代表火狐[firefox]内核识别码 //-webkit代表谷歌[chrome]/苹果[safari]内核识别码 // ...