ãã¡ã¤ã«ãã£ãã·ã¥ã©ã¤ãã©ãªãä½ã£ã¦ãã¦ãã£ãã·ã¥ãã£ã¬ã¯ããªé
ä¸ã®ç·ãã¡ã¤ã«ãµã¤ãºãè¨ç®ããå¿
è¦ãåºã¦ãã。ä»åã¯ãã¡ã¤ã«ãµã¤ãºè¨ç®ã«BSDç±æ¥ã®ã©ã¤ãã©ãª fts ã使ã£ã¦ã¿ã。
fts
Apple ã®ãªãã¡ã¬ã³ã¹ãçºãã¦ããã¨ãã£ã¬ã¯ããªèµ°æ»ã§ããã©ã¼ãã³ã¹ãèæ
®ãããªã fts ã使ãã®ãããã¨åºã¦ãã。
File-System Performance Guidelines: Iterating Directory Contents
ä¸è¨å
ã® Traversing Directories in BSD ã«è¨è¿°ãã。
調ã¹ã¦ã¿ãã¨ãã fts ã¨ããã®ã¯ BSDç³»OSã§ä½¿ããã¦ãããã£ã¬ã¯ããªèµ°æ»ç¨ã®ã©ã¤ãã©ãªã®ããã 。
fts_open - Linuxã®æã§è¡ãªããã¼ã¸
(ç¹å¾´)
・ãµããã£ã¬ã¯ããªãå«ããã¡ã¤ã«ã¨ãã£ã¬ã¯ããªã®ä¸è¦§ãåå¾ã§ãã
・ãã¹åã®ä»、statsæ§é ä½ãåå¾ã§ãã
・ã½ã¼ããå¯è½(æ¯è¼é¢æ°ã渡ããã¨ãã§ãã)
ãµããã£ã¬ã¯ããªãå帰çã«ãªã¹ãã¢ããã§ããã®ã§å¾æ¥ãããã readdirç³»ã®ã©ã¤ãã©ãªããã使ãåæãè¯ã。ã¾ã fts ã§ã¯ãã¹åã ãã§ãªã statsæ§é ä½ãåå¾ã§ããã®ã§ãã¡ã¤ã«ãµã¤ãºãè¨ç®ããå ´åã«ãããã statsé¢æ°ãå¼ã³åºãå¿
è¦ããªã。
以ä¸、ï¼ãã¡ã¤ã«/ãã£ã¬ã¯ããªæ¯ã«åå¾ã§ããæ§é ä½ FTSENT ã®å
容:
typedef struct _ftsent {
u_short fts_info; /* flags for FTSENT structure */
char *fts_accpath; /* access path */
char *fts_path; /* root path */
u_short fts_pathlen; /* strlen(fts_path) */
char *fts_name; /* file name */
u_short fts_namelen; /* strlen(fts_name) */
short fts_level; /* depth (-1 to N) */
int fts_errno; /* file errno */
long fts_number; /* local numeric value */
void *fts_pointer; /* local address value */
struct ftsent *fts_parent; /* parent directory */
struct ftsent *fts_link; /* next file structure */
struct ftsent *fts_cycle; /* cycle structure */
struct stat *fts_statp; /* stat(2) information */
} FTSENT;
※ man fts(3) ãã転è¼
å®è£
ä¾
ãããªæã。
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
- (IBAction)fts
{
int size = 0;
FTS* fts;
FTSENT *entry;
char* paths[] = {
[[self path] cStringUsingEncoding:NSUTF8StringEncoding], NULL
};
fts = fts_open(paths, 0, NULL);
while ((entry = fts_read(fts))) {
if (entry->fts_info & FTS_DP || entry->fts_level == 0) {
// ignore post-order
continue;
}
if (entry->fts_info & FTS_F) {
size += entry->fts_statp->st_size;
}
}
fts_close(fts);
}
å帰ã³ã¼ããè¦ããªãã®ã§ã¹ãããªãã¦ç°¡å。fts_openã§æ¸¡ããã¹ã¯é
åã§æ¸¡ãå¿
è¦ããã。ã¾ãé常ã ã¨åå¾ãªã¹ãå
ã«ãã£ã¬ã¯ããªãï¼åç¾ãã(pre-order 㨠post-order)ã®ã§éè¤ãããããªãå ´åã¯ä¸è¨ã³ã¼ãã®ããã«ï¼åç®ã«åºç¾ããã¿ã¤ãã³ã°(post-order)ãç¡è¦ããããã«ãã¦ãã(entry->fts_info & FTS_DP)。ã¾ã fts_open ã®å¼æ°ã§æ¸¡ãããã£ã¬ã¯ããªèªèº«ããªã¹ãã«å«ã¾ããªãããã«ãããã¬ãã«ã®ãã£ã¬ã¯ããª(etnry->fts_level==0 ã®ã±ã¼ã¹)ãç¡è¦ãã¦ãã。ãã¡ã¤ã«ãµã¤ãºã¯ FTSENTæ§é ä½ã®æ㤠fts_statp çµç±ã§ç°¡åã«åå¾ã§ãã。
fts_open ã®ç¬¬ï¼å¼æ°ã«ã¯ã½ã¼ãç¨ã®æ¯è¼é¢æ°ã渡ããã¨ãã§ãã。
FTS *fts_open(char * const *path_argv, int options,
int (*compar)(const FTSENT **, const FTSENT **));
ä¾ãã°ååé ã«ä¸è¦§ãåå¾ãããå ´åã¯
fts = fts_open(paths, 0, cmpare);
ã¨ã㦠compareé¢æ°ãç¨æãã¦ãã。
int cmpare(const FTSENT **a, const FTSENT **b)
{
return (strcasecmp((*a)->fts_name, (*b)->fts_name));
}
ä»ã®æ¹æ³ã¨ã®æ¯è¼
ãã¡ã¤ã«ãµã¤ãºè¨ç®ã®æ¹æ³ã¯ fts 以å¤ã«ã¯ readdir 㨠stats ã®çµã¿åããã®ä»、NSFileManager ã使ãæ¹æ³ããã。ãããã®æ¹æ³ã¨ fts ã使ãå ´åã®è¨ï¼ã¤ã®æ¹æ³ã«ã¤ãã¦ãããæéã®æ¯è¼ããã£ã¦ã¿ã。
æ¡ä»¶
ä¸è¨ã®ãã¹ããã¼ã¿(ãã£ã¬ã¯ããª、ãã¡ã¤ã«)ãä½æã、rootãã£ã¬ã¯ããªé
ä¸ã®ãã¡ã¤ã«ãµã¤ãºãè¨ç®ããã®ã«ããã£ãæéãå®æ©ã§è¨æ¸¬ãã。
æ¡ä»¶:ãã£ã¬ã¯ããªæ° 10x10x10、ãã¡ã¤ã«æ° 10x10x10、ï¼ãã¡ã¤ã«ã®ãµã¤ãº 1024ãã¤ã
å®æ©: iPhone 3GS / iOS 4.2.1
(root)
|--00
| |--00
| | |--00
| | | |--file-00
| | | |--file-01
| | | :
| | | |--file-09
| | |--01
| | :
| |
| |--01
: :
ã½ã¼ã¹
readdir ã使ã£ãå ´åã®ã½ã¼ã¹。
int countStdlib;
int sizeStdlib;
void countdir(const char* path) {
DIR* dir = opendir(path);
struct dirent* ent;
struct stat buf;
char newPath[4096];
if (dir) {
for(;;) {
if ((ent = readdir(dir)) == NULL) {
break;
}
strcpy(newPath, path);
strcat(newPath, "/");
strcat(newPath, ent->d_name);
if (ent->d_type == DT_DIR) {
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) {
countdir(newPath);
}
} else {
// file
stat(newPath, &buf);
sizeStdlib += buf.st_size;
countStdlib++;
}
}
}
closedir(dir);
}
- (IBAction)stdlib
{
countStdlib = 0;
sizeStdlib = 0;
countdir([[self path] cStringUsingEncoding:NSUTF8StringEncoding]);
}
NSFIleManager ã使ã£ãå ´åã®ã½ã¼ã¹。
- (IBAction)cocoa
{
int count = 0;
int size = 0;
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError* error = nil;
NSString* path = [self path];
for (NSString* filename in [fileManager enumeratorAtPath:[self path]]) {
NSDictionary* attributes = [fileManager
attributesOfItemAtPath:[path stringByAppendingPathComponent:filename]
error:&error];
if ([[attributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular]) {
count++;
size += [[attributes objectForKey:NSFileSize] intValue];
}
}
}
çµæ
fts 6.6ç§
readdir 8.5ç§
NSFileManager 40.6ç§
fts ãä¸çªéãã readdirã¨ã®å·®ã¯ããã»ã©å¤§ãããªã。readdir ã®é
ã 2ç§è¿ãã¯é¢æ°ã®å帰å¦ç㨠statsé¢æ°ã§å¼ã³åºãåæ°ãå¢ãã¦ããåã®ãªã¼ããããã¨æããã。NSFileManager ã¯ãªãã¸ã§ã¯ãã®çæã«ãããªã¼ããããã大ããäºæ³éãä»ã®ï¼ã¤ã¨æ¯ã¹ã¦ããªãé
ã。
ãã¡ã¤ã«ãµã¤ãºã®åå¾å¦çãé¤ãã¦åç´ãªä¸è¦§åå¾ã ãã«çµã£ã¦å®è¡ãã¦ã¿ãã¨æ¬¡ã®ããã«ãªã。
fts 1.3ç§ (FTS_NOSTAT ãªãã·ã§ã³)
readdir 1.1ç§
NSFileManager 11.0ç§
å
¨ä½çã«ããªãæéãç縮ã§ãããã¨ãã statså®è¡ã®å¦çãæ¯è¼çéããã¨ãåãã。
èå¯
fts 㯠readdir ã¨ã»ã¼åãããã©ã¼ãã³ã¹ãæã¡ãªãã、readdirãããç°¡æ½ã«ã³ã¼ããè¨è¿°ã§ãã。ã¾ãæ¨æºã§ statsæ
å ±ã®åå¾ãã½ã¼ãå¦çãè¡ãããªã©é«æ©è½ã§ãã。fts ã使ããå¦çç³»(iOSå«ã)ã§ããã°ãã¡ããå©ç¨ããæ¹ãä½ãã¨ä¾¿å©ã ãã。NSFileManager ã¯ä»ã®ï¼ã¤ã«æ¯ã¹ãã¨é度æ§è½ã§ããªãå£ã。ãã cocoaã§è¨è¿°ã§ããã¡ãªãããããã®ã§å¯¾è±¡ãã¼ã¿éãå°ãªãå ´åã§ããã°ããã使ãã®ãæªãã¯ãªã。
ãªãæ§è½ãåç¨åº¦ã¨ãªãã¨ããä¸ã¤æ°ã«ãªãã®ã¯ã¡ã¢ãªã®ãããããªã³ã。Instrumentsã使ãã·ãã¥ã¬ã¼ã¿ä¸ã§ã®ã¡ã¢ãªã®å¤åã調ã¹ã¦ã¿ãã¨ãã次ã®ããã«ãªã£ã。
(1) fts
770KB→934KB (+164KB)
(2) readdir
762KB→934KB(+172KB)
(3) NSFileManager
1MB → 27MB(+26MB)
fts 㨠readdir ã¯ã»ã¨ãã©å¤ããã、両æ¹å
±ã«ã¡ã¢ãªã®å©ç¨éã¯å¤ãç¡ã。ä¸æ¹ NSFileManager ã®å ´å㯠NSString ã®çæã³ã¹ãã大ããããªãã®ã¡ã¢ãªãæ¶è²»ãã¦ãã。
ãã¾ã:fts ã½ã¼ãæã®æ§è½
å
ã®ã±ã¼ã¹ã§ã¯ã½ã¼ããè¡ã£ã¦ããªãã£ã。ãã¹åã§ã®ã½ã¼ãå¦çãå
¥ããæã®æéãè¨æ¸¬ãã¦ã¿ã。
:
fts = fts_open(paths, 0, cmpare);
:
}
int cmpare(const FTSENT **a, const FTSENT **b)
{
return (-strcasecmp((*a)->fts_name, (*b)->fts_name)); // ãã¹åéé
}
çµæ㯠6.6ç§ã¨ã½ã¼ãæªæå®æã¨å¤ãããªã。念ã®ãããã¹å
容ã NSLog ã§åºãã¦ç¢ºèªãã¦ã¿ããã¡ããã¨ãã¹åéé ã§ä¸è¦§ãåå¾ã§ãã¦ã。ããã¯éããª。
ãµã³ãã«
GitHub ããã©ãã。
ftsSample at 2011-03-07 from xcatsan/iOS-Sample-Code - GitHub
å®è¡ããã¨ãã¿ã³ã®è¼ã£ãç»é¢ãç¾ãã。
"setup directories" ãã¿ããããã¨ãã¹ãç¨ã®ãã£ã¬ã¯ããª/ãã¡ã¤ã«ãçæããã。ããã¯æ°åç§ããããã¤ã³ã¹ãã¼ã«å¾ã®æåã®ä¸åã ãã®å®è¡ã§è¯ã。
BSD fts .... fts ã«ãããã¡ã¤ã«ãµã¤ãºè¨ç®
stdlib ... readdir ã使ã£ããã¡ã¤ã«ãµã¤ãºè¨ç®
Cocoa ... NSFileManager ã使ã£ããã¡ã¤ã«ãµã¤ãºè¨ç®
åèæ
å ±
fts_open
ftsã§ãã¡ã¤ã«é層ãåå¾ãã。: Xoå¼ å®é¨å®¤(labo.xo-ox.net)
FreeBSDã®lsãèªã fts(3)ã§lsãä½ã£ã¦ã¿ãã~。 - ãã¯ãã¹
Recursive read directory - verzeichnis rekursiv auslesen - dirent - GIDForums
Manpage of READDIR
dirent