PDA

View Full Version : [C] Calcolare dimensione directory


sam333
06-03-2013, 17:12
Ciao a tutti questo è il mio codice che mi permette di leggere il contenuto di una directory

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>



int main (void)
{
DIR *directory;


struct stat dim;
struct dirent *dir;


directory=opendir("H:/");


if(directory!=NULL){
while((dir= readdir(directory))!=NULL) {

puts(dir->d_name);


}
}
else{

perror("Impossibile aprire destinazione!");
}



closedir(directory);

system("pause");
free(dir);
return 0;
}


ora io ho due domande :

1) Come faccio a vedere(o calcolare) la dimensione di questa directory?
2) Se questa directory avesse altre cartelle come faccio a leggere anche il loro contenuto?


grazie come sempre a tutti in anticipo!:D

sottovento
06-03-2013, 18:49
Puoi usare le primitive contenute in <sys/stat.h>.
Vale a dire, una volta ottenuto il nome del file, ne fai uno stat().

La stat() ti ritornera' le informazioni che ti servono, quali la dimensione del file, se il file e' un regolare/directory/link/... oltre che data di creazione, modifica, ...

Se il file e' regolare, sommi le dimensioni.
Se il file e' directory, la puoi scandire ricorsivamente (e' piu' facile, ma puoi ovviamente fare anche iterativamente)

Vincenzo1968
06-03-2013, 19:44
Per Windows:

http://img203.imageshack.us/img203/57/scandir01.jpg

http://img62.imageshack.us/img62/9236/scandir02.jpg


ScanDir.h

#ifndef _MY_SCANDIR_
#define _MY_SCANDIR_

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

void DirWalk (LPCTSTR pszRootPath, BOOL fRecurse, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

#endif


ScanDir.c

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>

#include <stdlib.h>
#include <stdio.h>

#include "ScanDir.h"

BOOL IsChildDir (WIN32_FIND_DATA *lpFindData)
{
return
(
(lpFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindData->cFileName[0] != __TEXT('.'))
);
}

BOOL FindNextChildDir (HANDLE hFindFile, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound = FALSE;
do
{
fFound = FindNextFile(hFindFile, lpFindData);
} while (fFound && !IsChildDir(lpFindData));

return(fFound);
}

HANDLE FindFirstChildDir (LPTSTR szPath, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound;
HANDLE hFindFile = FindFirstFile(szPath, lpFindData);

if (hFindFile != INVALID_HANDLE_VALUE)
{
fFound = IsChildDir(lpFindData);
if (!fFound)
fFound = FindNextChildDir(hFindFile, lpFindData);

if (!fFound)
{
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}

return(hFindFile);
}

void GetParentDirectory(LPCTSTR szPath, LPTSTR szParent)
{
size_t nLen;
nLen = _tcslen(szPath);

_tcscpy(szParent, szPath);


if ( szPath[0] == '\\' )
return;

while ( nLen > 0 )
{
if ( *(szParent + nLen-1) == '\\' )
{
*(szParent + nLen-1) = '\0';
break;
}

--nLen;
}
}

// Percorre la struttura della directory.
// Se il campo pDW->fRecurse è TRUE, percorre ricorsivamente anche le sottodirectory.
void DirWalkRecurse (LPDIRWALKDATA pDW, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
HANDLE hFind;
pDW->szCurrDir[0] = '\0';

pDW->nDepth++;

pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, __TEXT("%*s"), pDW->nIndent, __TEXT(""));


// Imposta il buffer alla directory iniziale e chiama la funzione evento
// fornita dall'utente.
_tcscpy(&pDW->szBuf[pDW->nIndent], pDW->szCurrPath);

if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);


// Inizia a leggere il contenuto della directory iniziale
_tcscpy(pDW->szCurrDir, pDW->szCurrPath);
_tcscat(pDW->szCurrDir, __TEXT("\\*.*"));

hFind = FindFirstFile( pDW->szCurrDir, &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);

while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if ( !pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)) )
{
_stprintf(
pDW->szBuf,
pDW->fIsDir ? __TEXT("%*s[%s]") : __TEXT("%*s%s"),
pDW->nIndent, __TEXT(""),
pDW->FindData.cFileName);

// Per ogni file ( o sottodirectory ) trovato,
// chiamiamo la funzione fornita dall'utente
// passandogli i dati relativi tramite il puntatore alla struct pDW.
if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);

}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);

// se fRecurse è TRUE, leggiamo ricorsivamente le sottodirectory
if (pDW->fRecurse)
{
// Ottiene la prima directory figlia
hFind = FindFirstChildDir( pDW->szCurrDir, &pDW->FindData );
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Passa alla directory figlia
_tcscat(pDW->szCurrPath, __TEXT("\\"));
_tcscat(pDW->szCurrPath, pDW->FindData.cFileName);

DirWalkRecurse(pDW, pfnOnChange);

// Ritorna alla directory genitore
GetParentDirectory(pDW->szCurrPath, pDW->szPathParent);
_tcscpy(pDW->szCurrPath, pDW->szPathParent);

pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}

if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}

// Funzioni esportate
/////////////////////////////////////////////////////////////

// Il parametro pszRootPath è il percorso completo della directory da esaminare
// Il parametro fRecurse è un valore booleano che indica
// se vogliamo leggere anche le sottodirectory. Se impostato a FALSE, la funzione
// legge solo la directory passata nel parametro pszRootPath
// Il parametro pfnOnChange è un puntatore a una funzione evento che deve essere
// implementata dal client ( il programma che utilizza la DLL )

void DirWalk (LPCTSTR pszRootPath, BOOL fRecurse, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
DIRWALKDATA DW;

DW.szBuf[0] = '\0';
DW.szCurrDir[0] = '\0';
DW.szCurrPath[0] = '\0';
DW.szInitPath[0] = '\0';
DW.szPathParent[0] = '\0';

// nDepth è usato per controllare l'indentazione. Il valore -1
// fa si che il primo livello sia visualizzato allineato a sinistra
DW.nDepth = -1;

DW.fRecurse = fRecurse;

_tcscpy(DW.szInitPath, pszRootPath);
_tcscpy(DW.szCurrPath, pszRootPath);

// Leggiamo il contenuto della directory passata nel parametro pszRootPath.
// Se il parametro fRecurse è TRUE, leggiamo anche le sottodirectory
DirWalkRecurse(&DW, pfnOnChange);
}



ScanDirClient.c

#include <windows.h>

#include <stdio.h>
#include "scandir.h"

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
printf("# -> %s\n", pDW->szBuf);
}

int main(int argc, char* argv[])
{
if( argc < 2 )
return -1;

DirWalk(argv[1], TRUE, OnChange);

return 0;
}

Vincenzo1968
06-03-2013, 19:52
Per la dimensione della directory, su Windows, puoi utilizzare diverse api:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364232(v=vs.85).aspx

Vincenzo1968
06-03-2013, 20:37
Questo invece è l'esempio per Linux, tratto dal bel libro di W. Richard Stevens e Stephen A. Rago:

http://img818.imageshack.us/img818/7471/scandirlinux.jpg

apue.h

/* Our own header, to be included before all standard system headers */

#ifndef _APUE_H
#define _APUE_H

#if defined(SOLARIS)
#define _XOPEN_SOURCE 500 /* Single UNIX Specification, Version 2 for Solaris 9 */
#define CMSG_LEN(x) _CMSG_DATA_ALIGN(sizeof(struct cmsghdr)+(x))
#elif !defined(BSD)
#define _XOPEN_SOURCE 600 /* Single UNIX Specification, Version 3 */
#endif

#include <sys/types.h> /* some systems still require this */
#include <sys/stat.h>
#include <sys/termios.h> /* for winsize */
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif
#include <stdio.h> /* for convenience */
#include <stdlib.h> /* for convenience */
#include <stddef.h> /* for offsetof */
#include <string.h> /* for convenience */
#include <unistd.h> /* for convenience */
#include <signal.h> /* for SIG_ERR */

#define MAXLINE 4096 /* max line length */

/*
* Default file access permissions for new files.
*/
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

/*
* Default permissions for new directories.
*/
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)

typedef void Sigfunc(int); /* for signal handlers */

#if defined(SIG_IGN) && !defined(SIG_ERR)
#define SIG_ERR ((Sigfunc *)-1)
#endif

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

/*
* Prototypes for our own functions.
*/
char *path_alloc(int *); /* {Prog pathalloc} */
long open_max(void); /* {Prog openmax} */
void clr_fl(int, int); /* {Prog setfl} */
void set_fl(int, int); /* {Prog setfl} */
void pr_exit(int); /* {Prog prexit} */
void pr_mask(const char *); /* {Prog prmask} */
Sigfunc *signal_intr(int, Sigfunc *); /* {Prog signal_intr_function} */

int tty_cbreak(int); /* {Prog raw} */
int tty_raw(int); /* {Prog raw} */
int tty_reset(int); /* {Prog raw} */
void tty_atexit(void); /* {Prog raw} */
#ifdef ECHO /* only if <termios.h> has been included */
struct termios *tty_termios(void); /* {Prog raw} */
#endif

void sleep_us(unsigned int); /* {Ex sleepus} */
ssize_t readn(int, void *, size_t); /* {Prog readn_writen} */
ssize_t writen(int, const void *, size_t); /* {Prog readn_writen} */
void daemonize(const char *); /* {Prog daemoninit} */

int s_pipe(int *); /* {Progs streams_spipe sock_spipe} */
int recv_fd(int, ssize_t (*func)(int,
const void *, size_t));/* {Progs recvfd_streams recvfd_sockets} */
int send_fd(int, int); /* {Progs sendfd_streams sendfd_sockets} */
int send_err(int, int,
const char *); /* {Prog senderr} */
int serv_listen(const char *); /* {Progs servlisten_streams servlisten_sockets} */
int serv_accept(int, uid_t *); /* {Progs servaccept_streams servaccept_sockets} */
int cli_conn(const char *); /* {Progs cliconn_streams cliconn_sockets} */
int buf_args(char *, int (*func)(int,
char **)); /* {Prog bufargs} */

int ptym_open(char *, int); /* {Progs3 ptyopen_streams ptyopen_bsd ptyopen_linux} */
int ptys_open(char *); /* {Progs3 ptyopen_streams ptyopen_bsd ptyopen_linux} */
#ifdef TIOCGWINSZ
pid_t pty_fork(int *, char *, int, const struct termios *,
const struct winsize *); /* {Prog ptyfork} */
#endif

int lock_reg(int, int, int, off_t, int, off_t); /* {Prog lockreg} */
#define read_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))

pid_t lock_test(int, int, off_t, int, off_t); /* {Prog locktest} */

#define is_read_lockable(fd, offset, whence, len) \
(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
#define is_write_lockable(fd, offset, whence, len) \
(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)

void err_dump(const char *, ...); /* {App misc_source} */
void err_msg(const char *, ...);
void err_quit(const char *, ...);
void err_exit(int, const char *, ...);
void err_ret(const char *, ...);
void err_sys(const char *, ...);

void log_msg(const char *, ...); /* {App misc_source} */
void log_open(const char *, int, int);
void log_quit(const char *, ...);
void log_ret(const char *, ...);
void log_sys(const char *, ...);

void TELL_WAIT(void); /* parent/child from {Sec race_conditions} */
void TELL_PARENT(pid_t);
void TELL_CHILD(pid_t);
void WAIT_PARENT(void);
void WAIT_CHILD(void);

#endif /* _APUE_H */



scandir.c

#include "apue.h"
#include <dirent.h>
#include <limits.h>
/* function type that is called for each filename */
typedef int Myfunc(const char *, const struct stat *, int);
static Myfunc myfunc;
static int myftw(char *, Myfunc *);
static int dopath(Myfunc *);
static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;

int main(int argc, char *argv[])
{
int ret;
if (argc != 2)
{
printf("usage: scandir <starting-pathname>");
return -1;
}

ret = myftw(argv[1], myfunc); /* does it all */
ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock;
if (ntot == 0)
ntot = 1; /* avoid divide by 0; print 0 for all counts */
printf("regular files = %7ld, %5.2f %%\n", nreg,
nreg*100.0/ntot);
printf("directories = %7ld, %5.2f %%\n", ndir,
ndir*100.0/ntot);
printf("block special = %7ld, %5.2f %%\n", nblk,
nblk*100.0/ntot);
printf("char special = %7ld, %5.2f %%\n", nchr,
nchr*100.0/ntot);
printf("FIFOs = %7ld, %5.2f %%\n", nfifo,
nfifo*100.0/ntot);
printf("symbolic links = %7ld, %5.2f %%\n", nslink,
nslink*100.0/ntot);
printf("sockets = %7ld, %5.2f %%\n", nsock,
nsock*100.0/ntot);
exit(ret);
}

/*
* Descend through the hierarchy, starting at "pathname".
* The caller's func() is called for every file.
*/
#define FTW_F 1 /* file other than directory */
#define FTW_D 2 /* directory */
#define FTW_DNR 3 /* directory that can't be read */
#define FTW_NS 4 /* file that we can't stat */
static char *fullpath; /* contains full pathname for every file */
static int /* we return whatever func() returns */
myftw(char *pathname, Myfunc *func)
{
int len;
//fullpath = path_alloc(&len); /* malloc's for PATH_MAX+1 bytes */

len = PATH_MAX * sizeof(char) + 1;
fullpath = (char*)malloc(len);
if ( !fullpath )
{
printf("Memoria insufficiente, addio!\n");
return -1;
}

strncpy(fullpath, pathname, len); /* protect against */
fullpath[len-1] = 0; /* buffer overrun */
return(dopath(func));
}

/*
* Descend through the hierarchy, starting at "fullpath".
* If "fullpath" is anything other than a directory, we lstat() it,
* call func(), and return. For a directory, we call ourself
* recursively for each name in the directory.
*/
static int /* we return whatever func() returns */
dopath(Myfunc* func)
{
struct stat statbuf;
struct dirent *dirp;
DIR *dp;
int ret;
char *ptr;
if (lstat(fullpath, &statbuf) < 0) /* stat error */
return(func(fullpath, &statbuf, FTW_NS));
if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory */
return(func(fullpath, &statbuf, FTW_F));
/*
* It's a directory. First call func() for the directory,
* then process each filename in the directory.
*/
if ((ret = func(fullpath, &statbuf, FTW_D)) != 0)
return(ret);
ptr = fullpath + strlen(fullpath); /* point to end of fullpath */
*ptr++ = '/';
*ptr = 0;
if ((dp = opendir(fullpath)) == NULL) /* can't read directory */
return(func(fullpath, &statbuf, FTW_DNR));
while ((dirp = readdir(dp)) != NULL) {
if (strcmp(dirp->d_name, ".") == 0 ||
strcmp(dirp->d_name, "..") == 0)
continue; /* ignore dot and dot-dot */
strcpy(ptr, dirp->d_name); /* append name after slash */
if ((ret = dopath(func)) != 0) /* recursive */
break; /* time to leave */
}
ptr[-1] = 0; /* erase everything from slash onwards */
if (closedir(dp) < 0)
{
printf("can't close directory %s", fullpath);
return -1;
}
return(ret);
}

static int
myfunc(const char *pathname, const struct stat *statptr, int type)
{
switch (type) {
case FTW_F:
switch (statptr->st_mode & S_IFMT) {
case S_IFREG: nreg++; break;
case S_IFBLK: nblk++; break;
case S_IFCHR: nchr++; break;
case S_IFIFO: nfifo++; break;
case S_IFLNK: nslink++; break;
case S_IFSOCK: nsock++; break;
case S_IFDIR: printf("for S_IFDIR for %s", pathname); break;
}
break;
case FTW_D:
ndir++;
break;
case FTW_DNR:
printf("can't read directory %s", pathname);
break;
case FTW_NS:
printf("stat error for %s", pathname);
break;
default:
printf("unknown type %d for pathname %s", type, pathname);
}

return(0);
}

sam333
07-03-2013, 13:39
Puoi usare le primitive contenute in <sys/stat.h>.
Vale a dire, una volta ottenuto il nome del file, ne fai uno stat().

La stat() ti ritornera' le informazioni che ti servono, quali la dimensione del file, se il file e' un regolare/directory/link/... oltre che data di creazione, modifica, ...

Se il file e' regolare, sommi le dimensioni.
Se il file e' directory, la puoi scandire ricorsivamente (e' piu' facile, ma puoi ovviamente fare anche iterativamente)

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>

int main (int argc, char **argv) {


DIR *directory;
struct stat dim;
struct dirent *dir;


directory=opendir("H:/");


if(directory!=NULL){
while((dir= readdir(directory))!=NULL) {

puts(dir->d_name);

stat(dir->d_name, &dim);
printf ("\tDimensione : %f KB\n\n", float(dim.st_size)/1024);
}
}
else{

perror("Impossibile aprire destinazione!");
}



closedir(directory);


free(dir);

system ("PAUSE");
return 0;
}

Ho seguito il tuo consiglio e ho utilizzato stat :D ma mi da la dimensione dei file sbagliata come mai?:muro: se gli do da input il nome preciso del file che mi da la dimensione giusta, se no mi da un numero completamente sballato :muro:

sam333
07-03-2013, 13:40
Per la dimensione della directory, su Windows, puoi utilizzare diverse api:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa364232(v=vs.85).aspx

Vincenzo1968 non c'è una versione un po più "Sintetica"?:eek: o un alternativa?

Vincenzo1968
07-03-2013, 14:30
Si c'è:

http://img708.imageshack.us/img708/1429/compactdirwalk.jpg


#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>

void getDirInfo(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;

if( (dp = opendir(dir)) == NULL )
{
fprintf(stderr, "Impossibile aprire la directory: \"%s\". Addio!\n", dir);
return;
}

chdir(dir);

while( (entry = readdir(dp)) != NULL )
{
lstat(entry->d_name, &statbuf);

if( S_ISDIR(statbuf.st_mode) )
{
/* ignoriamo . and .. */
if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0 )
continue;

printf("%*s%s/\n", depth, "", entry->d_name);

/* nuovo livello d'indentazione */
getDirInfo(entry->d_name, depth + 4);
}
else
{
printf("%*s%s\n", depth, "", entry->d_name);
}
}

chdir("..");

closedir(dp);
}

int main(int argc, char* argv[])
{
char *topdir, pwd[2] = ".";

if (argc != 2)
topdir = pwd;
else
topdir = argv[1];

printf("Scansione della directory \"%s\"\n", topdir);

getDirInfo(topdir, 0);

printf("Finito!\n");

return 0;
}

sam333
07-03-2013, 15:51
grazie mille!:D mi sono studiato un po il tuo codice e ho due domande :

1) c'è un'alternativa alla libreria "unistd.h"?perchè non è solo per linux?non credo che ci sia su visual c++

2)sai per caso come mai mi da le dimensioni sballate?:muro:

Vincenzo1968
07-03-2013, 16:27
grazie mille!:D mi sono studiato un po il tuo codice e ho due domande :

1) c'è un'alternativa alla libreria "unistd.h"?perchè non è solo per linux?non credo che ci sia su visual c++

2)sai per caso come mai mi da le dimensioni sballate?:muro:

Be careful! Il codice è mio, si, nel senso che l'ho adattato. Ma il codice originale non ricordo più in quale libro/sito l'ho preso. Me lo sono ritrovato nel fottìo di esempi di programmazione che ho accumulato nei vari anni ma purtroppo non ho trovato il riferimento all'articolo/libro/sito originale.

Per quanto riguarda la prima domanda, potresti usare delle librerie che astraggono dal particolare sistrema operativo, tipo QT o Boost. Oppure puoi, più semplicemente, impacchettare le due versioni all'interno di direttive condizionali(#ifdef __linux__, etc).

Per quanto riguarda la domanda 2, no, non lo so. Il consiglio di Sottovento va nella direzione giusta. Non capisco cosa intendi per "se gli do il nome del file preciso". Per forza devi darglielo preciso altrimenti come si fa? :confused:

;)

sam333
07-03-2013, 17:04
Be careful! Il codice è mio, si, nel senso che l'ho adattato. Ma il codice originale non ricordo più in quale libro/sito l'ho preso. Me lo sono ritrovato nel fottìo di esempi di programmazione che ho accumulato nei vari anni ma purtroppo non ho trovato il riferimento all'articolo/libro/sito originale.

Per quanto riguarda la prima domanda, potresti usare delle librerie che astraggono dal particolare sistrema operativo, tipo QT o Boost. Oppure puoi, più semplicemente, impacchettare le due versioni all'interno di direttive condizionali(#ifdef __linux__, etc).

Per quanto riguarda la domanda 2, no, non lo so. Il consiglio di Sottovento va nella direzione giusta. Non capisco cosa intendi per "se gli do il nome del file preciso". Per forza devi darglielo preciso altrimenti come si fa? :confused:

;)

se gli do il nome preciso nel senso che gli metto come directory es. "C://text.txt" se invece gli passo d_name mi da una dimensione sballata come vedi nel codice che ho scritto e nn capisco perchè:muro:


Comunque o provato a riadattare il codice e come al solito non ci riesco-_-


#ifdef _linux
#include <unistd.h>

#else
#include "stdafx.h"
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>

#endif


non va bene?mi dice #endif imprevisto e che la libreria è stata ignorata

Vincenzo1968
07-03-2013, 17:35
Ecco:

http://img22.imageshack.us/img22/6521/dimdir.jpg


#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdint.h>

void getDirInfo(char *dir, int depth, uint64_t *pDim)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;

if( (dp = opendir(dir)) == NULL )
{
fprintf(stderr, "Impossibile aprire la directory: \"%s\". Addio!\n", dir);
return;
}

chdir(dir);

while( (entry = readdir(dp)) != NULL )
{
lstat(entry->d_name, &statbuf);

//*pDim += statbuf.st_size;

if( S_ISDIR(statbuf.st_mode) )
{
/* ignoriamo . and .. */
if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0 )
continue;

*pDim += statbuf.st_size;
printf("%*s%s/\n", depth, "", entry->d_name);

/* nuovo livello d'indentazione */
getDirInfo(entry->d_name, depth + 4, pDim);
}
else
{
*pDim += statbuf.st_size;
printf("%*s%s\n", depth, "", entry->d_name);
}
}

chdir("..");

closedir(dp);
}

int main(int argc, char* argv[])
{
uint64_t dim = 0;

char *topdir, pwd[2] = ".";

if (argc != 2)
topdir = pwd;
else
topdir = argv[1];

printf("Scansione della directory \"%s\"\n", topdir);

getDirInfo(topdir, 0, &dim);

printf("\nLa dimensione in byte della directory \"%s\" e': %llu\n", topdir, (unsigned long long)dim);

exit(0);
}

Vincenzo1968
07-03-2013, 17:38
Se invece vuoi ottenere la dimensione totale, cioè compresa la dimensione di file e directory nascoste, devi fare così:


#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdint.h>

void getDirInfo(char *dir, int depth, uint64_t *pDim)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;

if( (dp = opendir(dir)) == NULL )
{
fprintf(stderr, "Impossibile aprire la directory: \"%s\". Addio!\n", dir);
return;
}

chdir(dir);

while( (entry = readdir(dp)) != NULL )
{
lstat(entry->d_name, &statbuf);

*pDim += statbuf.st_size;

if( S_ISDIR(statbuf.st_mode) )
{
/* ignoriamo . and .. */
if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0 )
continue;

//*pDim += statbuf.st_size;
printf("%*s%s/\n", depth, "", entry->d_name);

/* nuovo livello d'indentazione */
getDirInfo(entry->d_name, depth + 4, pDim);
}
else
{
//*pDim += statbuf.st_size;
printf("%*s%s\n", depth, "", entry->d_name);
}
}

chdir("..");

closedir(dp);
}

int main(int argc, char* argv[])
{
uint64_t dim = 0;

char *topdir, pwd[2] = ".";

if (argc != 2)
topdir = pwd;
else
topdir = argv[1];

printf("Scansione della directory \"%s\"\n", topdir);

getDirInfo(topdir, 0, &dim);

printf("\nLa dimensione in byte della directory \"%s\" e': %llu\n", topdir, (unsigned long long)dim);

exit(0);
}

Vincenzo1968
07-03-2013, 17:43
Per le direttive di compilazione condizionale puoi dare un'occhiata alla soluzione postata da AnonimoVeneziano per il punto A del contest 19.

Eccolo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#if _WIN32
#include <Windows.h>
#define RESTRICT __restrict
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
#define fseeko _fseeki64
#define ftello _ftelli64

const char* files_dir = ".\\All\\*";

#else

#include <stdint.h>
#include <stdbool.h>
#include <dirent.h>
#define RESTRICT restrict
#define TRUE true
#define FALSE false
const char* files_dir = "./All/";
#endif

#define DEFAULT_LINE_NUM 100000
#define MB_MULTIPLIER 1024*1024ULL
#define GB_MULTIPLIER 1024*1024*1024ULL
#define IS_SPECIAL_DIRECTORY(x) (x[0] == '.' && \
(x[1] == '.' || x[1] == '\0'))

uint8_t file_nums = 0;
size_t text_size = 0;
char* RESTRICT full_text = NULL;
uint32_t lines_num = 0;
int64_t output_size_bytes = 0;
int64_t written_bytes = 0;
char* RESTRICT * RESTRICT lines_ptrs = NULL;
const char* usage_string = "Usage: c19input NameInputFile [-DFileSize]\n\n"
"The size of the output file is defined in this way:\n\n"
"-D1MB\toutput file is 1MB\n-D1GiB\t output file is 1 GB\n\n"
"The maximum file size is 55 GiB";

size_t get_file_size(const char* RESTRICT fname) {
size_t size;
FILE* f = fopen(fname, "r");
fseeko(f, 0L, SEEK_END);
size = ftello(f);
fclose(f);
return size;
}

void read_files(char* RESTRICT * RESTRICT fnames, int fnums) {
size_t pos_counter = 0;
size_t* RESTRICT files_size =
(size_t* RESTRICT)malloc(sizeof(size_t)*fnums);

for (int i = 0; i < fnums; ++i) {
files_size[i] = get_file_size(fnames[i]);
text_size += files_size[i];
}

full_text = (char * RESTRICT) malloc(sizeof(char)*(text_size+1));

// Read the entire text of files into the array
for (int i = 0; i < fnums; ++i) {
FILE* f = fopen(fnames[i], "r");
pos_counter += fread(full_text+pos_counter, sizeof(char), files_size[i], f);
fclose(f);
}

full_text[text_size] = '\0';

free(files_size);
}

#if !_WIN32
bool load_files(const char* directory) {

DIR* RESTRICT dir_obj = opendir(directory);
struct dirent* RESTRICT dir_struct;
char * RESTRICT * RESTRICT files_names;
const uint16_t path_size = strlen(directory);

int count = 0;

if (dir_obj == NULL)
return TRUE;

while ((dir_struct = readdir(dir_obj)) != NULL) {
//printf("File name: %s\n", dir_struct->d_name);
if (!IS_SPECIAL_DIRECTORY(dir_struct->d_name))
++file_nums;
}

rewinddir(dir_obj);

files_names = malloc(file_nums*sizeof(char*));

while ((dir_struct = readdir(dir_obj)) != NULL) {
if (!IS_SPECIAL_DIRECTORY(dir_struct->d_name)) {
int name_size = strlen(dir_struct->d_name);
int size = path_size + name_size + 1;

files_names[count] = malloc(sizeof(char)*size);
strncpy(files_names[count], directory, path_size);
strncpy(files_names[count]+path_size, dir_struct->d_name, name_size);
//printf("%s\n", files_names[count]);
++count;
}
}

closedir(dir_obj);

//printf("%d\n", file_nums);
//printf("Size of dir: %d\n", path_size);

// Read files
read_files(files_names, file_nums);

for (int i = 0; i < file_nums; ++i)
free((void*)files_names[i]);

free((void**)files_names);

return FALSE;
}
#else

bool load_files(const char* directory) {

WIN32_FIND_DATA find_data;
HANDLE hFind;
char * RESTRICT * RESTRICT files_names;
const uint16_t path_size = strlen(directory)-1;

int count = 0;
hFind = FindFirstFile(directory, &find_data);
if ( hFind == INVALID_HANDLE_VALUE)
return TRUE;

do {
//printf("File name: %s\n", dir_struct->d_name);
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
++file_nums;
} while (FindNextFile(hFind, &find_data));

FindClose(hFind);
hFind = FindFirstFile(directory, &find_data);

files_names =
(char* RESTRICT * RESTRICT) malloc(file_nums*sizeof(char*));

do {
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
int name_size = strlen(find_data.cFileName);
int size = path_size + name_size + 1;
files_names[count] =
(char* RESTRICT)malloc(sizeof(char)*size);
strncpy(files_names[count], directory, path_size);
strncpy(files_names[count]+path_size, find_data.cFileName, name_size+1);
//printf("%s\n", files_names[count]);
++count;
}
} while (FindNextFile(hFind, &find_data));

FindClose(hFind);

//printf("%d\n", file_nums);
//printf("Size of dir: %d\n", path_size);

// Read files
read_files(files_names, file_nums);

for (int i = 0; i < file_nums; ++i)
free((void*)files_names[i]);

free((void**)files_names);

return FALSE;
}

#endif

// Determines the number of lines and normalizes the text
void process_lines() {
lines_ptrs =
(char* RESTRICT * RESTRICT) malloc(sizeof(char*)*DEFAULT_LINE_NUM);
uint32_t correction = 0;
uint32_t curr_max_lines = DEFAULT_LINE_NUM;
lines_ptrs[0] = full_text;
bool has_character = FALSE;

for (size_t i = 0; i <= text_size; ++i) {
switch (full_text[i]) {
default: {
full_text[i-correction] = full_text[i];
has_character = TRUE;
break;
}
case '\t': {
full_text[i-correction] = ' ';
break;
}
case '\n': {
if (full_text[i-correction-1] != '\0') {
if (has_character)
lines_ptrs[++lines_num] = &full_text[i-correction+1];
full_text[i-correction] = '\0';
has_character = FALSE;
} else
++correction;
break;
}
case '\r': {
if (full_text[i-correction-1] != '\0') {
if (has_character)
lines_ptrs[++lines_num] = &full_text[i-correction+1];
full_text[i-correction] = '\0';
has_character = FALSE;
} else
++correction;
break;
}
case ' ': {
if (full_text[i-correction-1] != ' ' && has_character)
full_text[i-correction] = ' ';
else
++correction;
break;
}

}
// Expand line buffer
if (lines_num >= curr_max_lines) {
curr_max_lines = 2*curr_max_lines;
char* RESTRICT * RESTRICT new_lines_ptr =
(char* RESTRICT * RESTRICT) malloc(sizeof(char*)*curr_max_lines);
memcpy((void* RESTRICT)new_lines_ptr, (const void* RESTRICT)lines_ptrs, lines_num);
free((void*)lines_ptrs);
lines_ptrs = new_lines_ptr;
}
}
}

void shuffle_lines() {
for (uint32_t i = lines_num-1; i > 0; --i) {
uint32_t rand_idx = rand() % (i+1);
char* temp = lines_ptrs[i];
lines_ptrs[i] = lines_ptrs[rand_idx];
lines_ptrs[rand_idx] = temp;
}
}

bool generate_output(FILE* output) {
for (uint32_t i = 0; i < lines_num && written_bytes < output_size_bytes; ++i) {
int32_t str_len = strlen(lines_ptrs[i]);
if (str_len + written_bytes > output_size_bytes)
str_len = output_size_bytes - written_bytes - 1;
written_bytes += fwrite(lines_ptrs[i], sizeof(char), str_len, output) + 1;
fputc('\n', output);
}

if (written_bytes >= output_size_bytes)
return FALSE;

return TRUE;
}

void show_usage() {
printf("%s\n\n", usage_string);
}

int main(int argc, char **argv) {

bool error = FALSE;
FILE* output_file = NULL;

if (argc == 2) {
output_size_bytes = 1024*1024ULL;
} else if (argc == 3) {
char *arg2 = argv[2];
uint8_t unit_idx = 0;
char size[3] = { 0 };
uint64_t size_num;

if (strncmp(arg2, "-D", 2)) goto parse_error;

while (*(arg2+2+unit_idx) != '\0' &&
isdigit(*(arg2+2+unit_idx))) {
if ( unit_idx >= 3 ) goto parse_error;
size[unit_idx++] = *(arg2+2+unit_idx);
}
size_num = atoi(size);

if (size_num == 0) goto parse_error;

if (!strncmp(arg2+2+unit_idx, "GiB", 3))
size_num = size_num*GB_MULTIPLIER;
else if (!strncmp(arg2+2+unit_idx, "MB", 2))
size_num = size_num*MB_MULTIPLIER;
else goto parse_error;

output_size_bytes = size_num;
} else {

parse_error:
show_usage();
return 1;
}

srand(time(NULL));

//printf("Started loading the files\n");
clock_t t = clock();
error = load_files(files_dir);

printf("Files loaded, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

if (error) {
if (full_text)
free(full_text);
return 1;
}

output_file = fopen(argv[1], "w");

//printf("Started processing the files\n");
t = clock();

process_lines();
printf("File processing finished, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

//printf("Started final file output\n");
t = clock();

do {
shuffle_lines();
} while (generate_output(output_file));
printf("Final file output finished, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

free((void*)full_text);
free((void*)lines_ptrs);
fclose(output_file);

return 0;
}


;)

sam333
07-03-2013, 17:50
Per le direttive di compilazione condizionale puoi dare un'occhiata alla soluzione postata da AnonimoVeneziano per il punto A del contest 19.

Eccolo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#if _WIN32
#include <Windows.h>
#define RESTRICT __restrict
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
#define fseeko _fseeki64
#define ftello _ftelli64

const char* files_dir = ".\\All\\*";

#else

#include <stdint.h>
#include <stdbool.h>
#include <dirent.h>
#define RESTRICT restrict
#define TRUE true
#define FALSE false
const char* files_dir = "./All/";
#endif

#define DEFAULT_LINE_NUM 100000
#define MB_MULTIPLIER 1024*1024ULL
#define GB_MULTIPLIER 1024*1024*1024ULL
#define IS_SPECIAL_DIRECTORY(x) (x[0] == '.' && \
(x[1] == '.' || x[1] == '\0'))

uint8_t file_nums = 0;
size_t text_size = 0;
char* RESTRICT full_text = NULL;
uint32_t lines_num = 0;
int64_t output_size_bytes = 0;
int64_t written_bytes = 0;
char* RESTRICT * RESTRICT lines_ptrs = NULL;
const char* usage_string = "Usage: c19input NameInputFile [-DFileSize]\n\n"
"The size of the output file is defined in this way:\n\n"
"-D1MB\toutput file is 1MB\n-D1GiB\t output file is 1 GB\n\n"
"The maximum file size is 55 GiB";

size_t get_file_size(const char* RESTRICT fname) {
size_t size;
FILE* f = fopen(fname, "r");
fseeko(f, 0L, SEEK_END);
size = ftello(f);
fclose(f);
return size;
}

void read_files(char* RESTRICT * RESTRICT fnames, int fnums) {
size_t pos_counter = 0;
size_t* RESTRICT files_size =
(size_t* RESTRICT)malloc(sizeof(size_t)*fnums);

for (int i = 0; i < fnums; ++i) {
files_size[i] = get_file_size(fnames[i]);
text_size += files_size[i];
}

full_text = (char * RESTRICT) malloc(sizeof(char)*(text_size+1));

// Read the entire text of files into the array
for (int i = 0; i < fnums; ++i) {
FILE* f = fopen(fnames[i], "r");
pos_counter += fread(full_text+pos_counter, sizeof(char), files_size[i], f);
fclose(f);
}

full_text[text_size] = '\0';

free(files_size);
}

#if !_WIN32
bool load_files(const char* directory) {

DIR* RESTRICT dir_obj = opendir(directory);
struct dirent* RESTRICT dir_struct;
char * RESTRICT * RESTRICT files_names;
const uint16_t path_size = strlen(directory);

int count = 0;

if (dir_obj == NULL)
return TRUE;

while ((dir_struct = readdir(dir_obj)) != NULL) {
//printf("File name: %s\n", dir_struct->d_name);
if (!IS_SPECIAL_DIRECTORY(dir_struct->d_name))
++file_nums;
}

rewinddir(dir_obj);

files_names = malloc(file_nums*sizeof(char*));

while ((dir_struct = readdir(dir_obj)) != NULL) {
if (!IS_SPECIAL_DIRECTORY(dir_struct->d_name)) {
int name_size = strlen(dir_struct->d_name);
int size = path_size + name_size + 1;

files_names[count] = malloc(sizeof(char)*size);
strncpy(files_names[count], directory, path_size);
strncpy(files_names[count]+path_size, dir_struct->d_name, name_size);
//printf("%s\n", files_names[count]);
++count;
}
}

closedir(dir_obj);

//printf("%d\n", file_nums);
//printf("Size of dir: %d\n", path_size);

// Read files
read_files(files_names, file_nums);

for (int i = 0; i < file_nums; ++i)
free((void*)files_names[i]);

free((void**)files_names);

return FALSE;
}
#else

bool load_files(const char* directory) {

WIN32_FIND_DATA find_data;
HANDLE hFind;
char * RESTRICT * RESTRICT files_names;
const uint16_t path_size = strlen(directory)-1;

int count = 0;
hFind = FindFirstFile(directory, &find_data);
if ( hFind == INVALID_HANDLE_VALUE)
return TRUE;

do {
//printf("File name: %s\n", dir_struct->d_name);
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
++file_nums;
} while (FindNextFile(hFind, &find_data));

FindClose(hFind);
hFind = FindFirstFile(directory, &find_data);

files_names =
(char* RESTRICT * RESTRICT) malloc(file_nums*sizeof(char*));

do {
if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
int name_size = strlen(find_data.cFileName);
int size = path_size + name_size + 1;
files_names[count] =
(char* RESTRICT)malloc(sizeof(char)*size);
strncpy(files_names[count], directory, path_size);
strncpy(files_names[count]+path_size, find_data.cFileName, name_size+1);
//printf("%s\n", files_names[count]);
++count;
}
} while (FindNextFile(hFind, &find_data));

FindClose(hFind);

//printf("%d\n", file_nums);
//printf("Size of dir: %d\n", path_size);

// Read files
read_files(files_names, file_nums);

for (int i = 0; i < file_nums; ++i)
free((void*)files_names[i]);

free((void**)files_names);

return FALSE;
}

#endif

// Determines the number of lines and normalizes the text
void process_lines() {
lines_ptrs =
(char* RESTRICT * RESTRICT) malloc(sizeof(char*)*DEFAULT_LINE_NUM);
uint32_t correction = 0;
uint32_t curr_max_lines = DEFAULT_LINE_NUM;
lines_ptrs[0] = full_text;
bool has_character = FALSE;

for (size_t i = 0; i <= text_size; ++i) {
switch (full_text[i]) {
default: {
full_text[i-correction] = full_text[i];
has_character = TRUE;
break;
}
case '\t': {
full_text[i-correction] = ' ';
break;
}
case '\n': {
if (full_text[i-correction-1] != '\0') {
if (has_character)
lines_ptrs[++lines_num] = &full_text[i-correction+1];
full_text[i-correction] = '\0';
has_character = FALSE;
} else
++correction;
break;
}
case '\r': {
if (full_text[i-correction-1] != '\0') {
if (has_character)
lines_ptrs[++lines_num] = &full_text[i-correction+1];
full_text[i-correction] = '\0';
has_character = FALSE;
} else
++correction;
break;
}
case ' ': {
if (full_text[i-correction-1] != ' ' && has_character)
full_text[i-correction] = ' ';
else
++correction;
break;
}

}
// Expand line buffer
if (lines_num >= curr_max_lines) {
curr_max_lines = 2*curr_max_lines;
char* RESTRICT * RESTRICT new_lines_ptr =
(char* RESTRICT * RESTRICT) malloc(sizeof(char*)*curr_max_lines);
memcpy((void* RESTRICT)new_lines_ptr, (const void* RESTRICT)lines_ptrs, lines_num);
free((void*)lines_ptrs);
lines_ptrs = new_lines_ptr;
}
}
}

void shuffle_lines() {
for (uint32_t i = lines_num-1; i > 0; --i) {
uint32_t rand_idx = rand() % (i+1);
char* temp = lines_ptrs[i];
lines_ptrs[i] = lines_ptrs[rand_idx];
lines_ptrs[rand_idx] = temp;
}
}

bool generate_output(FILE* output) {
for (uint32_t i = 0; i < lines_num && written_bytes < output_size_bytes; ++i) {
int32_t str_len = strlen(lines_ptrs[i]);
if (str_len + written_bytes > output_size_bytes)
str_len = output_size_bytes - written_bytes - 1;
written_bytes += fwrite(lines_ptrs[i], sizeof(char), str_len, output) + 1;
fputc('\n', output);
}

if (written_bytes >= output_size_bytes)
return FALSE;

return TRUE;
}

void show_usage() {
printf("%s\n\n", usage_string);
}

int main(int argc, char **argv) {

bool error = FALSE;
FILE* output_file = NULL;

if (argc == 2) {
output_size_bytes = 1024*1024ULL;
} else if (argc == 3) {
char *arg2 = argv[2];
uint8_t unit_idx = 0;
char size[3] = { 0 };
uint64_t size_num;

if (strncmp(arg2, "-D", 2)) goto parse_error;

while (*(arg2+2+unit_idx) != '\0' &&
isdigit(*(arg2+2+unit_idx))) {
if ( unit_idx >= 3 ) goto parse_error;
size[unit_idx++] = *(arg2+2+unit_idx);
}
size_num = atoi(size);

if (size_num == 0) goto parse_error;

if (!strncmp(arg2+2+unit_idx, "GiB", 3))
size_num = size_num*GB_MULTIPLIER;
else if (!strncmp(arg2+2+unit_idx, "MB", 2))
size_num = size_num*MB_MULTIPLIER;
else goto parse_error;

output_size_bytes = size_num;
} else {

parse_error:
show_usage();
return 1;
}

srand(time(NULL));

//printf("Started loading the files\n");
clock_t t = clock();
error = load_files(files_dir);

printf("Files loaded, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

if (error) {
if (full_text)
free(full_text);
return 1;
}

output_file = fopen(argv[1], "w");

//printf("Started processing the files\n");
t = clock();

process_lines();
printf("File processing finished, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

//printf("Started final file output\n");
t = clock();

do {
shuffle_lines();
} while (generate_output(output_file));
printf("Final file output finished, it took: %f seconds\n", ((float)(clock() - t)) / CLOCKS_PER_SEC);

free((void*)full_text);
free((void*)lines_ptrs);
fclose(output_file);

return 0;
}


;)

grazie tante!!:D sto già iniziando a riscrivere il codice:) ma posso chiederti un ultima cosa?:help:

Vincenzo1968
07-03-2013, 19:31
grazie tante!!:D sto già iniziando a riscrivere il codice:) ma posso chiederti un ultima cosa?:help:

Che sia l'ultima però eh! :huh:


Scheeeeerzo! Chiedi pure ;)

sam333
07-03-2013, 19:45
Che sia l'ultima però eh! :huh:


Scheeeeerzo! Chiedi pure ;)

sìsì tranquillo:D comunque come posso fare per andare nella directory desktop per esempio senza sapere il nome utente?O.o come implemento il codice?:mbe:

Vincenzo1968
07-03-2013, 22:38
http://img29.imageshack.us/img29/5486/dimscandirwindows2.jpg


ScanDir.h:

#ifndef _MY_SCANDIR_
#define _MY_SCANDIR_

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

#endif


ScanDir.c:

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#include "ScanDir.h"

BOOL IsChildDir (WIN32_FIND_DATA *lpFindData)
{
return
(
(lpFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindData->cFileName[0] != __TEXT('.'))
);
}

BOOL FindNextChildDir (HANDLE hFindFile, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound = FALSE;
do
{
fFound = FindNextFile(hFindFile, lpFindData);
} while (fFound && !IsChildDir(lpFindData));

return(fFound);
}

HANDLE FindFirstChildDir (LPTSTR szPath, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound;
HANDLE hFindFile = FindFirstFile(szPath, lpFindData);

if (hFindFile != INVALID_HANDLE_VALUE)
{
fFound = IsChildDir(lpFindData);
if (!fFound)
fFound = FindNextChildDir(hFindFile, lpFindData);

if (!fFound)
{
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}

return(hFindFile);
}

void GetParentDirectory(LPCTSTR szPath, LPTSTR szParent)
{
size_t nLen;
nLen = _tcslen(szPath);

_tcscpy(szParent, szPath);


if ( szPath[0] == '\\' )
return;

while ( nLen > 0 )
{
if ( *(szParent + nLen-1) == '\\' )
{
*(szParent + nLen-1) = '\0';
break;
}

--nLen;
}
}

// Percorre la struttura della directory.
// Se il campo pDW->fRecurse è TRUE, percorre ricorsivamente anche le sottodirectory.m
void DirWalkRecurse (LPDIRWALKDATA pDW, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
HANDLE hFind;
pDW->szCurrDir[0] = '\0';

pDW->nDepth++;

pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, __TEXT("%*s"), pDW->nIndent, __TEXT(""));


// Imposta il buffer alla directory iniziale e chiama la funzione evento
// fornita dall'utente.
_tcscpy(&pDW->szBuf[pDW->nIndent], pDW->szCurrPath);

if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);


// Inizia a leggere il contenuto della directory iniziale
_tcscpy(pDW->szCurrDir, pDW->szCurrPath);
_tcscat(pDW->szCurrDir, __TEXT("\\*.*"));

hFind = FindFirstFile( pDW->szCurrDir, &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);

while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if ( !pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)) )
{
_stprintf(
pDW->szBuf,
pDW->fIsDir ? __TEXT("%*s[%s]") : __TEXT("%*s%s"),
pDW->nIndent, __TEXT(""),
pDW->FindData.cFileName);

*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;

// Per ogni file ( o sottodirectory ) trovato,
// chiamiamo la funzione fornita dall'utente
// passandogli i dati relativi tramite il puntatore alla struct pDW.
if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);

}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);

// se fRecurse è TRUE, leggiamo ricorsivamente le sottodirectory
if (pDW->fRecurse)
{
// Ottiene la prima directory figlia
hFind = FindFirstChildDir( pDW->szCurrDir, &pDW->FindData );
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Passa alla directory figlia
_tcscat(pDW->szCurrPath, __TEXT("\\"));
_tcscat(pDW->szCurrPath, pDW->FindData.cFileName);

DirWalkRecurse(pDW, pDim, pfnOnChange);

// Ritorna alla directory genitore
GetParentDirectory(pDW->szCurrPath, pDW->szPathParent);
_tcscpy(pDW->szCurrPath, pDW->szPathParent);

pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}

if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}

// Funzioni esportate
/////////////////////////////////////////////////////////////

// Il parametro pszRootPath è il percorso completo della directory da esaminare
// Il parametro fRecurse è un valore booleano che indica
// se vogliamo leggere anche le sottodirectory. Se impostato a FALSE, la funzione
// legge solo la directory passata nel parametro pszRootPath
// Il parametro pfnOnChange è un puntatore a una funzione evento che deve essere
// implementata dal client ( il programma che utilizza la DLL )

void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
DIRWALKDATA DW;

DW.szBuf[0] = '\0';
DW.szCurrDir[0] = '\0';
DW.szCurrPath[0] = '\0';
DW.szInitPath[0] = '\0';
DW.szPathParent[0] = '\0';

// nDepth è usato per controllare l'indentazione. Il valore -1
// fa si che il primo livello sia visualizzato allineato a sinistra
DW.nDepth = -1;

DW.fRecurse = fRecurse;

_tcscpy(DW.szInitPath, pszRootPath);
_tcscpy(DW.szCurrPath, pszRootPath);

// Leggiamo il contenuto della directory passata nel parametro pszRootPath.
// Se il parametro fRecurse è TRUE, leggiamo anche le sottodirectory
DirWalkRecurse(&DW, pDim, pfnOnChange);
}


ScanDirClient.c:

#include <windows.h>

#include <stdio.h>
#include <stdint.h>
#include "scandir.h"

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
printf("# -> %s\n", pDW->szBuf);
}

int main(int argc, char* argv[])
{
uint64_t dim = 0;

if( argc < 2 )
return -1;

getDirInfo(argv[1], TRUE, &dim, OnChange);

printf("\nLa dimensione della directory \"%s\" e': %llu byte\n", argv[1], (unsigned long long)dim);

return 0;
}

Vincenzo1968
07-03-2013, 22:39
sìsì tranquillo:D comunque come posso fare per andare nella directory desktop per esempio senza sapere il nome utente?O.o come implemento il codice?:mbe:

Boh! :confused:

The_ouroboros
08-03-2013, 07:29
comunque come posso fare per andare nella directory desktop per esempio senza sapere il nome utente?O.o
La vedo dura


Inviato dal mio Sony Xperia P

wingman87
08-03-2013, 09:01
Non me ne intendo e quindi magari dico una cavolata, ma non dovrebbe usare queste funzioni?

GetUserProfileDirectory:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762280.aspx

OpenProcessToken:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa379295.aspx

GetCurrentProcess:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683179%28v=vs.85%29.aspx

sam333
08-03-2013, 13:52
ah in c non si può??sicuri??:eek:

van9
08-03-2013, 15:02
ah in c non si può??sicuri??:eek:

Si. La libreria standard del C:

- ha la funzione getenv() per recuperare informazioni dall'environment. Puoi usarla per recuperare la variabile "userprofile" ad esempio e poi costruirti la stringa finale che ti interessa del tipo "c:\Users\nome" con "\Desktop" aggiunta in coda;

- non ha nessuna funzione con cui puoi cambiare la current directory (in effetti non ha proprio alcun supporto per le directories).

Forse sarebbe meglio se ti studiassi un minimo cosa il C mette a disposizione prima di continuare verso il tuo obiettivo.

sam333
08-03-2013, 19:24
Si. La libreria standard del C:

- ha la funzione getenv() per recuperare informazioni dall'environment. Puoi usarla per recuperare la variabile "userprofile" ad esempio e poi costruirti la stringa finale che ti interessa del tipo "c:\Users\nome" con "\Desktop" aggiunta in coda;

- non ha nessuna funzione con cui puoi cambiare la current directory (in effetti non ha proprio alcun supporto per le directories).

Forse sarebbe meglio se ti studiassi un minimo cosa il C mette a disposizione prima di continuare verso il tuo obiettivo.

sìsì :mbe:

Vincenzo1968
09-03-2013, 14:51
Improved version for Linux: :D

- Reso il codice thread-safe: http://archive.cert.uni-stuttgart.de/bugtraq/2005/11/msg00044.html

- Aggiunto puntatore a funzione callback in modo da stampare i dati al di fuori della funzione che effettua la scansione. Così è più flessibile, come nella versione per Windows.


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

void getDirInfo(char *dirName, uint64_t *pDim, int depth, void (*pfnOnChange)(const char *pathName, int depth))
{
DIR *dir = NULL;
struct dirent entry;
struct dirent *entryPtr = NULL;
int retval = 0;
unsigned count = 0;
char pathName[PATH_MAX + 1];

dir = opendir(dirName);
if( dir == NULL )
{
printf("Error opening %s: %s", dirName, strerror(errno));
return;
}

depth++;

retval = readdir_r(dir, &entry, &entryPtr);
while( entryPtr != NULL )
{
struct stat entryInfo;

if( ( strncmp(entry.d_name, ".", PATH_MAX) == 0 ) ||
( strncmp(entry.d_name, "..", PATH_MAX) == 0 ) )
{
retval = readdir_r(dir, &entry, &entryPtr);
continue;
}

strncpy(pathName, dirName, PATH_MAX);
strncat(pathName, "/", PATH_MAX);
strncat(pathName, entry.d_name, PATH_MAX);

if( lstat(pathName, &entryInfo) == 0 )
{
*pDim += entryInfo.st_size;

if( S_ISDIR(entryInfo.st_mode) ) // directory
{
if ( pfnOnChange )
(*pfnOnChange)(pathName, depth);
getDirInfo(pathName, pDim, depth, pfnOnChange);
}
else if( S_ISREG(entryInfo.st_mode) ) // regular file
{
//printf("\t%s <> size: %lld bytes\n", pathName, (long long)entryInfo.st_size);
if ( pfnOnChange )
(*pfnOnChange)(pathName, depth);
}
else if( S_ISLNK(entryInfo.st_mode) ) // symbolic link
{
char targetName[PATH_MAX + 1];
if( readlink(pathName, targetName, PATH_MAX) != -1 )
{
//printf("\t%s -> %s\n", pathName, targetName);
if ( pfnOnChange )
(*pfnOnChange)(pathName, depth);
}
else
{
printf("\t%s -> (invalid symbolic link!)\n", pathName);
}
}
}
else
{
printf("Error lstat %s: %s\n", pathName, strerror(errno));
}

retval = readdir_r(dir, &entry, &entryPtr);
}

depth--;

closedir(dir);
}

void OnChange(const char *pathName, int depth)
{
printf("%*s%s\n", (depth - 1) * 3, "", pathName);
//printf("%s\n", pathName);
}

int main(int argc, char **argv)
{
uint64_t dim = 0;

if(argc != 2)
{
fprintf(stdout, "uso: %s <dirpath>\n", argv[0]);
fflush(stdout);
return -1;
}

getDirInfo(argv[1], &dim, 0, OnChange);
//getDirInfo(argv[1], &dim, 0, NULL);

fprintf(stdout, "La dimensione della directory \"%s\" e' di %llu byte.\n", argv[1], (unsigned long long)dim);

return 0;
}


http://img14.imageshack.us/img14/6478/dirwalklinux.jpg

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Vincenzo1968
09-03-2013, 15:59
Corretto piccolo bug nella versione Windows: non funzionava bene se compilato con: "Use Unicode character set" o "Use Multi-byte character set".

http://www.hwupgrade.org/public/style_emoticons/default/lol.png


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

//void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

BOOL IsChildDir (WIN32_FIND_DATA *lpFindData)
{
return
(
(lpFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindData->cFileName[0] != __TEXT('.'))
);
}

BOOL FindNextChildDir (HANDLE hFindFile, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound = FALSE;
do
{
fFound = FindNextFile(hFindFile, lpFindData);
} while (fFound && !IsChildDir(lpFindData));

return(fFound);
}

HANDLE FindFirstChildDir (LPTSTR szPath, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound;
HANDLE hFindFile = FindFirstFile(szPath, lpFindData);

if (hFindFile != INVALID_HANDLE_VALUE)
{
fFound = IsChildDir(lpFindData);
if (!fFound)
fFound = FindNextChildDir(hFindFile, lpFindData);

if (!fFound)
{
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}

return(hFindFile);
}

void GetParentDirectory(LPCTSTR szPath, LPTSTR szParent)
{
size_t nLen;
nLen = _tcslen(szPath);

_tcscpy(szParent, szPath);


if ( szPath[0] == '\\' )
return;

while ( nLen > 0 )
{
if ( *(szParent + nLen-1) == '\\' )
{
*(szParent + nLen-1) = '\0';
break;
}

--nLen;
}
}

// Percorre la struttura della directory.
// Se il campo pDW->fRecurse è TRUE, percorre ricorsivamente anche le sottodirectory.m
void DirWalkRecurse (LPDIRWALKDATA pDW, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
HANDLE hFind;
LARGE_INTEGER sz;
pDW->szCurrDir[0] = '\0';

pDW->nDepth++;

pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, __TEXT("%*s"), pDW->nIndent, __TEXT(""));


// Imposta il buffer alla directory iniziale e chiama la funzione evento
// fornita dall'utente.
_tcscpy(&pDW->szBuf[pDW->nIndent], pDW->szCurrPath);

if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);


// Inizia a leggere il contenuto della directory iniziale
_tcscpy(pDW->szCurrDir, pDW->szCurrPath);
_tcscat(pDW->szCurrDir, __TEXT("\\*.*"));

hFind = FindFirstFile( pDW->szCurrDir, &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);

while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if ( !pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)) )
{
_stprintf(
pDW->szBuf,
pDW->fIsDir ? __TEXT("%*s[%s]") : __TEXT("%*s%s"),
pDW->nIndent, __TEXT(""),
pDW->FindData.cFileName);

//*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;
sz.LowPart = pDW->FindData.nFileSizeLow;
sz.HighPart = pDW->FindData.nFileSizeHigh;
*pDim += sz.QuadPart;

// Per ogni file ( o sottodirectory ) trovato,
// chiamiamo la funzione fornita dall'utente
// passandogli i dati relativi tramite il puntatore alla struct pDW.
if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);

}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);

// se fRecurse è TRUE, leggiamo ricorsivamente le sottodirectory
if (pDW->fRecurse)
{
// Ottiene la prima directory figlia
hFind = FindFirstChildDir( pDW->szCurrDir, &pDW->FindData );
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Passa alla directory figlia
_tcscat(pDW->szCurrPath, __TEXT("\\"));
_tcscat(pDW->szCurrPath, pDW->FindData.cFileName);

DirWalkRecurse(pDW, pDim, pfnOnChange);

// Ritorna alla directory genitore
GetParentDirectory(pDW->szCurrPath, pDW->szPathParent);
_tcscpy(pDW->szCurrPath, pDW->szPathParent);

pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}

if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}

// Funzioni esportate
/////////////////////////////////////////////////////////////

// Il parametro pszRootPath è il percorso completo della directory da esaminare
// Il parametro fRecurse è un valore booleano che indica
// se vogliamo leggere anche le sottodirectory. Se impostato a FALSE, la funzione
// legge solo la directory passata nel parametro pszRootPath
// Il parametro pfnOnChange è un puntatore a una funzione evento che deve essere
// implementata dal client ( il programma che utilizza la DLL )

void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
DIRWALKDATA DW;

DW.szBuf[0] = '\0';
DW.szCurrDir[0] = '\0';
DW.szCurrPath[0] = '\0';
DW.szInitPath[0] = '\0';
DW.szPathParent[0] = '\0';

// nDepth è usato per controllare l'indentazione. Il valore -1
// fa si che il primo livello sia visualizzato allineato a sinistra
DW.nDepth = -1;

DW.fRecurse = fRecurse;

_tcscpy(DW.szInitPath, pszRootPath);
_tcscpy(DW.szCurrPath, pszRootPath);

// Leggiamo il contenuto della directory passata nel parametro pszRootPath.
// Se il parametro fRecurse è TRUE, leggiamo anche le sottodirectory
DirWalkRecurse(&DW, pDim, pfnOnChange);
}

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
_tprintf(_TEXT("%s\n"), pDW->szBuf);
}

//int main(int argc, char* argv[])
int _tmain(int argc, TCHAR *argv[])
{
uint64_t dim = 0;

if( argc < 2 )
return -1;

getDirInfo(argv[1], TRUE, &dim, OnChange);

printf("\nLa dimensione della directory \"%s\" e': %llu byte\n", argv[1], (unsigned long long)dim);

return 0;
}


http://img441.imageshack.us/img441/1318/scandir03.jpg

http://img6.imageshack.us/img6/7473/scandir04.jpg

sam333
10-03-2013, 19:27
Corretto piccolo bug nella versione Windows: non funzionava bene se compilato con: "Use Unicode character set" o "Use Multi-byte character set".

http://www.hwupgrade.org/public/style_emoticons/default/lol.png


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

//void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

BOOL IsChildDir (WIN32_FIND_DATA *lpFindData)
{
return
(
(lpFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindData->cFileName[0] != __TEXT('.'))
);
}

BOOL FindNextChildDir (HANDLE hFindFile, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound = FALSE;
do
{
fFound = FindNextFile(hFindFile, lpFindData);
} while (fFound && !IsChildDir(lpFindData));

return(fFound);
}

HANDLE FindFirstChildDir (LPTSTR szPath, WIN32_FIND_DATA *lpFindData)
{
BOOL fFound;
HANDLE hFindFile = FindFirstFile(szPath, lpFindData);

if (hFindFile != INVALID_HANDLE_VALUE)
{
fFound = IsChildDir(lpFindData);
if (!fFound)
fFound = FindNextChildDir(hFindFile, lpFindData);

if (!fFound)
{
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}

return(hFindFile);
}

void GetParentDirectory(LPCTSTR szPath, LPTSTR szParent)
{
size_t nLen;
nLen = _tcslen(szPath);

_tcscpy(szParent, szPath);


if ( szPath[0] == '\\' )
return;

while ( nLen > 0 )
{
if ( *(szParent + nLen-1) == '\\' )
{
*(szParent + nLen-1) = '\0';
break;
}

--nLen;
}
}

// Percorre la struttura della directory.
// Se il campo pDW->fRecurse è TRUE, percorre ricorsivamente anche le sottodirectory.m
void DirWalkRecurse (LPDIRWALKDATA pDW, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
HANDLE hFind;
LARGE_INTEGER sz;
pDW->szCurrDir[0] = '\0';

pDW->nDepth++;

pDW->nIndent = 3 * pDW->nDepth;
_stprintf(pDW->szBuf, __TEXT("%*s"), pDW->nIndent, __TEXT(""));


// Imposta il buffer alla directory iniziale e chiama la funzione evento
// fornita dall'utente.
_tcscpy(&pDW->szBuf[pDW->nIndent], pDW->szCurrPath);

if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);


// Inizia a leggere il contenuto della directory iniziale
_tcscpy(pDW->szCurrDir, pDW->szCurrPath);
_tcscat(pDW->szCurrDir, __TEXT("\\*.*"));

hFind = FindFirstFile( pDW->szCurrDir, &pDW->FindData);
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);

while (pDW->fOk)
{
pDW->fIsDir = pDW->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if ( !pDW->fIsDir || (!pDW->fRecurse && IsChildDir(&pDW->FindData)) )
{
_stprintf(
pDW->szBuf,
pDW->fIsDir ? __TEXT("%*s[%s]") : __TEXT("%*s%s"),
pDW->nIndent, __TEXT(""),
pDW->FindData.cFileName);

//*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;
sz.LowPart = pDW->FindData.nFileSizeLow;
sz.HighPart = pDW->FindData.nFileSizeHigh;
*pDim += sz.QuadPart;

// Per ogni file ( o sottodirectory ) trovato,
// chiamiamo la funzione fornita dall'utente
// passandogli i dati relativi tramite il puntatore alla struct pDW.
if ( pfnOnChange )
(*pfnOnChange)(pDW);
//printf("pDW->szBuf -----> %s\n", pDW->szBuf);

}
pDW->fOk = FindNextFile(hFind, &pDW->FindData);
}
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);

// se fRecurse è TRUE, leggiamo ricorsivamente le sottodirectory
if (pDW->fRecurse)
{
// Ottiene la prima directory figlia
hFind = FindFirstChildDir( pDW->szCurrDir, &pDW->FindData );
pDW->fOk = (hFind != INVALID_HANDLE_VALUE);
while (pDW->fOk)
{
// Passa alla directory figlia
_tcscat(pDW->szCurrPath, __TEXT("\\"));
_tcscat(pDW->szCurrPath, pDW->FindData.cFileName);

DirWalkRecurse(pDW, pDim, pfnOnChange);

// Ritorna alla directory genitore
GetParentDirectory(pDW->szCurrPath, pDW->szPathParent);
_tcscpy(pDW->szCurrPath, pDW->szPathParent);

pDW->fOk = FindNextChildDir(hFind, &pDW->FindData);
}

if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
}
pDW->nDepth--;
}

// Funzioni esportate
/////////////////////////////////////////////////////////////

// Il parametro pszRootPath è il percorso completo della directory da esaminare
// Il parametro fRecurse è un valore booleano che indica
// se vogliamo leggere anche le sottodirectory. Se impostato a FALSE, la funzione
// legge solo la directory passata nel parametro pszRootPath
// Il parametro pfnOnChange è un puntatore a una funzione evento che deve essere
// implementata dal client ( il programma che utilizza la DLL )

void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA))
{
DIRWALKDATA DW;

DW.szBuf[0] = '\0';
DW.szCurrDir[0] = '\0';
DW.szCurrPath[0] = '\0';
DW.szInitPath[0] = '\0';
DW.szPathParent[0] = '\0';

// nDepth è usato per controllare l'indentazione. Il valore -1
// fa si che il primo livello sia visualizzato allineato a sinistra
DW.nDepth = -1;

DW.fRecurse = fRecurse;

_tcscpy(DW.szInitPath, pszRootPath);
_tcscpy(DW.szCurrPath, pszRootPath);

// Leggiamo il contenuto della directory passata nel parametro pszRootPath.
// Se il parametro fRecurse è TRUE, leggiamo anche le sottodirectory
DirWalkRecurse(&DW, pDim, pfnOnChange);
}

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
_tprintf(_TEXT("%s\n"), pDW->szBuf);
}

//int main(int argc, char* argv[])
int _tmain(int argc, TCHAR *argv[])
{
uint64_t dim = 0;

if( argc < 2 )
return -1;

getDirInfo(argv[1], TRUE, &dim, OnChange);

printf("\nLa dimensione della directory \"%s\" e': %llu byte\n", argv[1], (unsigned long long)dim);

return 0;
}


http://img441.imageshack.us/img441/1318/scandir03.jpg

http://img6.imageshack.us/img6/7473/scandir04.jpg

ma scusa c'è un alternativa a chdir per visual c?:mbe:

Vincenzo1968
10-03-2013, 20:38
ma scusa c'è un alternativa a chdir per visual c?:mbe:

No, l'api di Windows è cervellotica! http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Windows api brain fuck... http://www.hwupgrade.org/public/style_emoticons/default/lol.png

lorenzo001
10-03-2013, 21:09
No, l'api di Windows è cervellotica! http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Per curiosità, perché è cervellotica la

SetCurrentDirectory
http://msdn.microsoft.com/en-us/library/aa365530.aspx

?

Vincenzo1968
10-03-2013, 22:05
Per curiosità, perché è cervellotica la

SetCurrentDirectory
http://msdn.microsoft.com/en-us/library/aa365530.aspx

?

No, non la SetCurrentDirectory, la api in generale: settantamila parametri da settare prima di poter chiamare una funzione: LOOOOOOOOOOOLLLLLL!!!

Confrontala un po' con la api Linux.

Guarda cosa c'è da fare per calcolare la dimensione di una file:


sz.LowPart = pDW->FindData.nFileSizeLow;
sz.HighPart = pDW->FindData.nFileSizeHigh;
*pDim += sz.QuadPart;


E il bello è che la documentazione MSDN dice che è sufficiente quest'altro codice:


*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;



Ma non funziona per file di dimensioni superiori a 4 GiB.

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

lorenzo001
11-03-2013, 14:53
Cosa c'entra la dimensione del file con quello di cui stiamo parlando ?

Cosa c'entra Linux?

:confused:

Vincenzo1968
11-03-2013, 15:02
Cosa c'entra la dimensione del file con quello di cui stiamo parlando ?


Ah non stiamo parlando di calcolare la dimensione di una directory? Senza sommare le dimensioni dei singoli file come fai? Con la sfera di cristallo?


Cosa c'entra Linux?

:confused:


Confrontala un po' con la api Linux.

lorenzo001
11-03-2013, 15:09
Ah non stiamo parlando di calcolare la dimensione di una directory? Senza sommare le dimensioni dei singoli file come fai? Con la sfera di cristallo?

Stavamo parlando di alternative alla chdir e quindi ho suggerito la SetCurrentDirectory ...

Che c'entra tutto quello che stai dicendo?

P.S. In ogni caso, il calcolo

*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;

ha solamente una cosa sbagliata ... il fatto che manca il cast di (MAXDWORD+1) ... il calcolo corretto è

*pDim += (pDW->FindData.nFileSizeHigh * ((ULONGLONG)(MAXDWORD+1)) + pDW->FindData.nFileSizeLow;

Vincenzo1968
11-03-2013, 15:22
Una volta, non ricordo più in quale talk-show, Nosferatu-Sallusti disse: "Cosa c'entra Marcello Dell'Utri con Silvio Berlusconi?".

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Vincenzo1968
11-03-2013, 15:24
Stavamo parlando di alternative alla chdir e quindi ho suggerito la SetCurrentDirectory ...

Che c'entra tutto quello che stai dicendo?

P.S. In ogni caso, il calcolo

*pDim += (pDW->FindData.nFileSizeHigh * (MAXDWORD+1)) + pDW->FindData.nFileSizeLow;

ha solamente una cosa sbagliata ... il fatto che manca il cast di (MAXDWORD+1) ... il calcolo corretto è

*pDim += (pDW->FindData.nFileSizeHigh * ((ULONGLONG)(MAXDWORD+1)) + pDW->FindData.nFileSizeLow;

Linux:

*pDim += entryInfo.st_size;

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

lorenzo001
11-03-2013, 15:44
Una volta, non ricordo più in quale talk-show, Nosferatu-Sallusti disse: "Cosa c'entra Marcello Dell'Utri con Silvio Berlusconi?".

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Mi dispiace ma non commento certe risposte che nulla hanno a che vedere (e non mi sembra neanche spiritosa ...).

Linux:

*pDim += entryInfo.st_size;

Il tipo di st_size è a 32 o 64 bit a seconda del tipo di compilazione.

I due valori low e high della struttura di Windows sono comunque due DWORD (a 32 bit) compatibili con i 32 bit (per la sola parte low) e con i 64 se prese insieme.

Se poi una semplice moltiplicazione (ovvero la composizione di due valori a 32 bit in uno a 64 bit) è un problema per un programmatore, forse è meglio che si dedichi ad altro (in maniera analoga, non è certo per questo che un OS può essere migliore di un altro ...).

Vincenzo1968
11-03-2013, 17:32
Comunque, Sam, ti conviene impacchettare tutto quanto in una bella shared library(.so/.dll).

Io mi sono creato le mie con una versione iterativa della funzione getDirInfo in modo da essere sicuro di non esaurire lo stack di sistema.
Può capitare, con la versione ricorsiva, se il livello di annidamento delle sottodirectory è alto(p. es. con la directory root).

La versione iterativa è pure più efficiente dal punto di vista delle prestazioni, è molto più veloce.

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Vincenzo1968
11-03-2013, 18:10
Ah, Sam, ricordati di compilare col flag -D _FILE_OFFSET_BITS=64 quando compili a 32 bit:


//getDirInfo(argv[1], &dim, 0, OnChange);
getDirInfo(argv[1], &dim, 0, NULL);


http://img7.imageshack.us/img7/617/readdir32.jpg

http://img443.imageshack.us/img443/8292/dimc19.jpg

Usare il flag _FILE_OFFSET_BITS=64, anziché la funzione readdir64_r, rende il codice portabile.

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

Vincenzo1968
11-03-2013, 18:30
Mi dispiace ma non commento certe risposte che nulla hanno a che vedere (e non mi sembra neanche spiritosa ...).


In effetti Nosferatu-Sallusti più che ridere fa piangere.

sam333
12-03-2013, 10:12
Comunque, Sam, ti conviene impacchettare tutto quanto in una bella shared library(.so/.dll).

Io mi sono creato le mie con una versione iterativa della funzione getDirInfo in modo da essere sicuro di non esaurire lo stack di sistema.
Può capitare, con la versione ricorsiva, se il livello di annidamento delle sottodirectory è alto(p. es. con la directory root).

La versione iterativa è pure più efficiente dal punto di vista delle prestazioni, è molto più veloce.

http://www.hwupgrade.org/public/style_emoticons/default/lol.png

lo so che è una figuraccia ma non so farlo:(

Vincenzo1968
12-03-2013, 11:41
lo so che è una figuraccia ma non so farlo:(

No che figuraccia, non nasciamo tutti imparati(cit.).

Ecco un esempio:

http://www.hwupgrade.it/forum/showpost.php?p=38937179&postcount=6

Vincenzo1968
12-03-2013, 13:39
Ecco Sam, da qui puoi scaricare la libreria statica precompilata per Linux:

http://www.filedropper.com/libreaddirtar

C'è la versione a 32 bit(X86), libreaddir32.a, e la versione a 64 bit(X86_64, AMD64), libreaddir64.a

Per usarla:

readdir.h

#ifndef MY_READDIR_H
#define MY_READDIR_H

void getDirInfo(char *dirName, uint64_t *pDim, int depth, void (*pfnOnChange)(const char *pathName, int depth, struct stat *statOut));

#endif /* MY_READDIR_H */


main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

#include "readdir.h"

// gcc -O3 -m32 main.c libreaddir32.a -o readdir32
// gcc -O3 -m64 main.c libreaddir64.a -o readdir64

void OnChange(const char *pathName, int depth, struct stat *statOut)
{
if ( S_ISDIR(statOut->st_mode) )
printf("%*sDirectory: %s\n", (depth - 1) * 3, "", pathName);
else
printf("%*s%s\n", (depth - 1) * 3, "", pathName);
}

int main(int argc, char **argv)
{
uint64_t dim = 0;

if(argc != 2)
{
fprintf(stdout, "uso: %s <dirpath>\n", argv[0]);
fflush(stdout);
return -1;
}

//getDirInfo(argv[1], &dim, 0, OnChange);
getDirInfo(argv[1], &dim, 0, NULL);

fprintf(stdout, "La dimensione della directory \"%s\" e' di %llu byte.\n", argv[1], (unsigned long long)dim);

return 0;
}


Compilare a 32 bit:

gcc -O3 -m32 main.c libreaddir32.a -o readdir32


Compilare a 64 bit:

gcc -O3 -m64 main.c libreaddir64.a -o readdir64


Più tardi ti posto le librerie statiche precompilate per Windows.

Vincenzo1968
12-03-2013, 17:18
Ecco, Sam, da qui puoi scaricare le static library per Windows/Visual Studio 2012:

http://www.filedropper.com/libreaddir

Uso:

readdir.h

#ifndef MY_READDIR_H
#define MY_READDIR_H

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

#endif /* MY_READDIR_H */


main.c

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#include "readdir.h"

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
_tprintf(_TEXT("%s\n"), pDW->szBuf);
}

//int main(int argc, char* argv[])
int _tmain(int argc, TCHAR *argv[])
{
uint64_t dim = 0;

if( argc < 2 )
return -1;

getDirInfo(argv[1], TRUE, &dim, OnChange);
//getDirInfo(argv[1], TRUE, &dim, NULL);

printf("\nLa dimensione della directory \"%s\" e': %llu byte\n", argv[1], (unsigned long long)dim);

return 0;
}


Copia i file libreaddir32.lib e libreaddir64.lib nella cartella dei sorgenti:

http://img266.imageshack.us/img266/6906/staticlib00.jpg

Per la configurazione a 32 bit indica al linker la libreria a 32 bit:

http://img407.imageshack.us/img407/2122/staticlib01.jpg



Per la configurazione a 64 bit indica al linker la libreria a 64 bit:

http://img195.imageshack.us/img195/6734/staticlib02.jpg



Se invece usi una versione precedente di Visual Studio(2010?), bisogna ricompilare le librerie con quella versione.

Visual Studio http://www.hwupgrade.org/public/style_emoticons/default/lol.png

sam333
12-03-2013, 17:40
grazie mille!!:D ora mi studierò per bene le librerie dinamiche

Vincenzo1968
12-03-2013, 17:41
Ecco le librerie per Visual Studio 2010:

http://www.filedropper.com/libreaddirvs2010

Vincenzo1968
13-03-2013, 10:27
Ecco le shared library per Linux:

http://www.filedropper.com/readdirsharedlibtar

Uso:

32 bit:

gcc -O3 -m32 -L. -lreaddir32 main.c -o readdir32

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

./readdir32 ~/Contest19


64 bit:

gcc -O3 -m64 -L. -lreaddir64 main.c -o readdir64

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

./readdir64 ~/Contest19


Se schiaffi la libreria in uno dei percorsi standard, tipo "/usr/local/lib", non c'è bisogno del comando export ;)

readdir.h

#ifndef MY_READDIR_H
#define MY_READDIR_H

#if defined _WIN32 || defined __CYGWIN__
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
#else
#if __GNUC__ >= 4
#define MYDLL_API __attribute__ ((visibility ("default")))
#else
#define MYDLL_API
#endif
#endif


#ifdef __cplusplus
extern "C" {
#endif

MYDLL_API void getDirInfo(char *dirName, uint64_t *pDim, int depth, void (*pfnOnChange)(const char *pathName, int depth, struct stat *statOut));

#ifdef __cplusplus
}
#endif

#endif /* MY_READDIR_H */


main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

#include "readdir.h"

void OnChange(const char *pathName, int depth, struct stat *statOut)
{
if ( S_ISDIR(statOut->st_mode) )
printf("%*sDirectory: %s\n", (depth - 1) * 3, "", pathName);
else
printf("%*s%s\n", (depth - 1) * 3, "", pathName);
}

int main(int argc, char **argv)
{
uint64_t dim = 0;

if(argc != 2)
{
fprintf(stdout, "uso: %s <dirpath>\n", argv[0]);
fflush(stdout);
return -1;
}

getDirInfo(argv[1], &dim, 0, OnChange);
//getDirInfo(argv[1], &dim, 0, NULL);

fprintf(stdout, "La dimensione della directory \"%s\" e' di %llu byte.\n", argv[1], (unsigned long long)dim);

return 0;
}

Vincenzo1968
13-03-2013, 12:30
Ecco le dll per Windows:

http://www.filedropper.com/libreaddirwinnew


Uso:

readdir.h

#ifndef MY_READDIR_H
#define MY_READDIR_H

#if defined _WIN32 || defined __CYGWIN__
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
#else
#if __GNUC__ >= 4
#define MYDLL_API __attribute__ ((visibility ("default")))
#else
#define MYDLL_API
#endif
#endif

#define ARRAY_SIZE(Array) (sizeof(Array) / sizeof((Array)[0]))

#ifdef __cplusplus
extern "C" {
#endif

// Dati usati dalla funzione DirWalkRecurse
typedef struct
{
TCHAR szInitPath[_MAX_DIR]; // Path iniziale
TCHAR szCurrPath[_MAX_DIR]; // Path corrente
TCHAR szPathParent[_MAX_DIR]; // Path genitore di szCurrPath
TCHAR szCurrDir[_MAX_DIR]; // Path temporaneo; ci servirà per la ricerca dei files
int nDepth; // Profondità
BOOL fRecurse; // impostare a TRUE per ottenere la scansione delle sottodirectory.
TCHAR szBuf[1024]; // Buffer per l'output formattato
int nIndent; // Contatore per l'indentazione
BOOL fOk; // Loop control flag
BOOL fIsDir; // Loop control flag
WIN32_FIND_DATA FindData; // Informazioni sui file
} DIRWALKDATA, *LPDIRWALKDATA;

MYDLL_API void getDirInfo(LPCTSTR pszRootPath, BOOL fRecurse, uint64_t *pDim, void (CALLBACK *pfnOnChange)(LPDIRWALKDATA));

#ifdef __cplusplus
}
#endif

#endif /* MY_READDIR_H */


main.c

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#include "readdir.h"

void CALLBACK OnChange(LPDIRWALKDATA pDW)
{
_tprintf(_TEXT("%s\n"), pDW->szBuf);
}

//int main(int argc, char* argv[])
int _tmain(int argc, TCHAR *argv[])
{
uint64_t dim = 0;

if( argc < 2 )
return -1;

getDirInfo(argv[1], TRUE, &dim, OnChange);

printf("\nLa dimensione della directory \"%s\" e': %llu byte\n", argv[1], (unsigned long long)dim);

return 0;
}


Ricordarsi di impostare il file d'importazione .lib:

32 bit:
http://img819.imageshack.us/img819/7447/scandirwindll01.jpg


64 bit
http://img835.imageshack.us/img835/2180/scandirwindll02.jpg

Ricordati di piazzare la dll nella stessa cartella dell'eseguibile o nella cartella di sistema, solitamente "C:\Windows\System32".