How can I get the date of when a file was created? I am running Windows.
On Windows, you should use the GetFileAttributesEx function for that.
For C, it depends on which operating system you are coding for. Files are a system dependent concept.
If you're system has it, you can go with the stat() (and friends) function: http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html.
On Windows you may use the GetFileTime() function: http://msdn.microsoft.com/en-us/library/ms724320%28v=vs.85%29.aspx.
Unix systems don't store the time of file creation. Unix systems do store the last time the file was read (if atime is turned on for that specific file system; sometimes it is disabled for speed), the last time the file was modified (mtime), and the last time the file's metadata changed (ctime).
See the stat(2) manpage for details on using it.
Use stat function
see here
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
struct tm* clock; // create a time structure
struct stat attrib; // create a file attribute structure
stat("afile.txt", &attrib); // get the attributes of afile.txt
clock = gmtime(&(attrib.st_mtime)); // Get the last modified time and put it into the time structure
Related
I have a target board running linux which has approximately around 5 million+ files in the directory. (This directory doesn't have any sub directories)
If i execute this program it takes several minutes to get the total space information.
Is there a faster way to accomplish this? Thanks
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
#include <errno.h>
void calcSpace(char *path, long long int *totalSpace)
{
DIR *dir; /* dir structure we are reading */
struct dirent *ent; /* directory entry currently being processed */
char absPath[200];
struct stat statbuf; /* buffer for stat()*/
long long int fileCount=0;
fprintf(stderr, "Opening dir %s\n", path);
dir = opendir(path);
if(NULL == dir) {
perror(path);
return;
}
while((ent = readdir(dir)))
{
fileCount++;
sprintf(absPath, "%s/%s", path, ent->d_name);
if(stat(absPath, &statbuf)) {
perror(absPath);
return;
}
*totalSpace= (*totalSpace) + statbuf.st_size;
}
fprintf(stderr, "Closing dir %s\n", path);
printf("fileCount=%lld.\n", fileCount);
closedir(dir);
}
int main(int argc, char *argv[])
{
char *dir;
long long int totalSpace=0;
if(argc > 1)
dir = argv[1];
else
dir = ".";
calcSpace(dir, &totalSpace);
printf("totalSpace=%lld\n", totalSpace);
return 0;
}
As stated in the comments, it seems that the main cost are the calls for stat and readdir.
Optimizing readdir calls
We can save some serious costs on the readdir costs using the getdents(2) syscall instead. This syscall is similar to 'readdir', but you can use it in order to read multiple directory entries in each syscall - greatly reducing the overhead of calling the readdir syscall for each entry.
A code example can be found in the man page I linked to. The importat thing to note is that you probably should fiddle around with the amount of entries read at a time using getdents (the count paramater - in the example it is 1024), to find the sweet spot for your configuration and machine (this step will probably give you the performance improvement you want over readdir).
Optimizing stat calls
It is recommended to use the fstatat(2) function instead of the regular stat you used (relevant man page for both). This is because the first paramter of fstatat(2) is a dirfd - file descriptor for the directory the file you are stating is under.
That means that you can open a file descriptor to the directory once (using open(2)), and then all fstatat calls will be done with this dirfd. This will optimize the stating process in the kernel (as the reference for the entire path and the directory itself shouldn't be resolved for every stat syscall anymore), and would probably make your code simpler and a little bit faster (as path concatenation will not be needed anymore).
While technically this is not an 'answer', some comments about the issue here:
Behind the scenes, most Linux file system represent files as 'inodes', with the directory representing list of names->inode. Depending on the file system, the list may be simple linear list, balanced tree, or a hash - which will improve on the performance of lookup, and the penalty for working with folders with large number of files.
Older operating systems (Vax VMS, and it's predecessors FILES-11) had to ability to open a file by a unique ID (file number, sequence number), in addition to opening a file by file path. In Linux space this will be equivalent to opening a file by inode number. This approach make it possible to open, or query for meta data with little overhead. Unfortunately, Unix/Linux does not have similar feature at the application level, and as much as I know, there are no plans to create such an interface. It will require significant upgrade to all file system drivers.
Another approach will be to implement multi-file stat system calls, which will benefit from being able to perform the file lookup for all files during a single scan. While type of system calls will speed up various utilities, it will not benefit most applications, which will usually stick to POSIX calls. it will be hard to implement such a feature, without changes to various file system drivers. I believe it's unlikely to be available soon.
I need modification time, creation time and change time of file in windows using cpp. I am using following code:
string filename = "D:\\hi.txt";
struct stat result;
if (stat(filename.c_str(), &result) == 0)
{
int a = 10;
auto mod_time = result.st_mtime;
cout << "modified time is: "<<mod_time<<endl;
}
Using this I am able to get modification and creation time. But, I am not able to get change time for the file. How should I get change time for file using cpp?
The definition of "change time" follows.
Modification time changes when the content of the file changes and
Change time changes even when the properties of the file change like
access permissions.
MSDN defines three timestamps for files: Creation Time, Last Access Time, Last Write Time. What you ask for looks in fact to be the Last Access Time.
In your example you use a Libc function stat() which is meant to work on all systems that have a C compiler. As it is, it may be too generic i.e. it does not represent all capabilities available inside a particular environment (MS Windows in your case), only a subset of generic properties.
At this link you can find the description of GetFileTime() WinAPI function that returns file times supported on Windows. If you write an application that is not meant to be ported to other platforms, you are better off using WinAPI for system-level things.
I have a problem in my project. There is a project folder on my desktop. I want to create a text file and write something include this text file. That is my code:
ofstream example("/Users/sample/Desktop/save.txt");
But I want to it could been run the other mac. I don't know what I should write addres for save.txt.
Can anyone help me?
Create a file and write some text to it is simple, here is a sample code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
std::ofstream o("/Users/sample/Desktop/save.txt");
o << "Hello, World\n" << std::endl;
return 0;
}
I hope that answers your question but I am not sure if i understand your question correctly, If not please add the details correctly of what you are trying to acheive.
[Update]:
Okay I guess the comment clears the problem.
Your real question is, You want to save the file in the desktop of the user who is playing the game. So getting the path of the current user's desktop is the problem.
I am not sure if there is an portable way to get desktop path but it can be done in following ways:
In Windows:
Using the SHGetSpecialFolderPath() function.
Sample code:
char saveLocation[MAX_PATH] = {0};
SHGetSpecialFolderPath(NULL, saveLocation, CSIDL_DESKTOPDIRECTORY, FALSE);
//Now saveLocation contains the path to the desktop
//Append your file name to it
strcat(saveLocation,"\\save.txt");
ofstream o(saveLocation);
In Linux:
By using environment variables $HOME
sample code:
string path(getenv("HOME"));
path += "/Desktop/save.txt";
ofstream o(path);
Rules defining where-you-should-save-file vary from platform to platform. One option would be to have it part of your compile script (that is you #define SAVEGAME_PATH as part of your compilation configuration), and thus your code itself remain more platform-agnostic.
The alternative is to find a save-data-management library that is already designed to be ported across different platforms. Whether it'd be a C or C++ or whatever-binary-interoperable library then no longer matters.
Just don't expect that to be part of C++ (the language).
if you want your program to run across platform,you'd better use the
relative path.
eg. "./output.txt",or better “GetSystemDirectory()”to obtain the system
directory to create a file,and then you could write or read the file
with the same path..
i'm writing a little c++ app to wrap around the opencv haar training function (namely cvCreateTreeCascadeClassifier). The function throws a whole load of output to the console and I wish to parse this output so that I can populate various variables in my code.
The function I wish to use is not part of the actual openCV library; instead it has to be built with my code as part of the project. All of the output from the the function is via printf.
Question: Is it possible to intercept the printf statements before they end up on the console? I've managed to redirect them using freopen but this seems a little clumsy as I then need to parse the file and then delete it when the function call is finished. Also, the function is likely to be running for several hours (and possibly even weeks!) so the size of the file might be an issue if its constantly being appended too.
Requirements: I need this app to be c++ and to run on both windows and linux (but have no problem with conditional compile statements if need be). I would also like to be able to still see my cout and cerr messages on the console (just not the printf).
My googling has removed my will to live! Can anyone help with a solution via either code example or pointers to places I should be looking for an answer?
Thanks
What you can do is:
create a pipe
make the writable end of the pipe the new stdout
read from the readable part of the pipe
Reading and writing should happen in different threads or you risk that your program starves on one end of the pipe.
Here's a sample how to do the redirection in unix & windows:
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
/* gcc defined unix */
#ifdef unix
#include <unistd.h>
#endif
#ifdef WIN32
#include <io.h>
#define pipe(X) _pipe(X,4096,O_BINARY)
#define fileno _fileno
#define dup2 _dup2
#define read _read
#endif
#include <assert.h>
int main()
{
int fds[2];
int res;
char buf[256];
int so;
res=pipe(fds);
assert(res==0);
so=fileno(stdout);
// close stdout handle and make the writable part of fds the new stdout.
res=dup2(fds[1],so);
assert(res!=-1);
printf("Hi there\n");
fflush(stdout);
// reading should happen in a different thread
res=read(fds[0],buf,sizeof(buf)-1);
assert(res>=0 && res<sizeof(buf));
buf[res]=0;
fprintf(stderr,"buf=>%s\n",buf);
return 0;
}
This code should print
buf=>Hi there
(I'm using assert here, because I am too lazy to do real error checking for this example)
Encapsulate the lib into an application, and pipe the application's output to your application. Now write a script so that you don't have to run the apps together every time with a pipe.
Take a look at: http://www.unix.com/programming/136225-reading-stdout-pipe.html it seems promising, but i never tried it.
I create a win32 console app in C++. I use some API (not mine, and I can not modify its sources). It Is written so that it writes some of its info onto console screen not asking... each time I call it (48 times per second) So I want to put it into some thread and limit its output capabilities, but I need to get notified when that thread will try to output some message which is important for me. I have message text in standard string. How to do such thing in C++ using boost?
Here's a crazy idea:
If the lib is using cout/cerr, you could replace the streambuf of these global variables with an implementation of your own. It would, on flush/data, check some thread-local variable to see if the data came from the thread that calls the library, then route it somewhere else (i.e. into a std::string/std::ostringstream) instead of to the regular cout/cerr streambufs. (Which you should keep around.)
If it's using c's stdout/stderr, I think it'd be harder to do properly, but it might be doable still. You'd need to create some pipes and route stuff back and forth. More of a C/unixy question then, which I don't know that much about... yet. :)
Hope it helps.
That feature does not exist in Boost. You can, however, use _dup2 to replace the standard out descriptor:
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <iostream>
#include <windows.h>
int main()
{
HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (0 == SetStdHandle(STD_OUTPUT_HANDLE, h)) {
std::fprintf(stderr, "`SetStdHandle` failed with error %d\n", (int)GetLastError());
return EXIT_FAILURE;
}
int h_desc = _open_osfhandle((long)h, 0);
_dup2(h_desc, STDOUT_FILENO);
std::printf("test\r\n"); // This actually writes to `h`.
std::fflush(stdout);
std::cout << "another test" << std::endl; // Also writes to `h`
CloseHandle(h);
return EXIT_SUCCESS;
}
Essentially what this trick does is allow you to redirect all writes to stdout, std::cout, and GetStdHandle(STD_OUTPUT_HANDLE) to a writable handle of your choosing (h). Of course, you can use CreatePipe to create the writable handle (h) and read from the readable end in another thread.
EDIT: If you are looking for a cross-platform solution, note that this trick is even easier on POSIX-compatible systems because dup2 is a standard function in unistd.h and "writable handles" are already descriptors.
I cannot think of a way to achieve in Boost what you want, as the problem is described.
However, this API behaviour is very perplexing. Spitting out reams of output to the console is a bit antisocial. Are you using a Debug build of the API library? Are you sure there's no way to configure the API such that it outputs this data to a different stream, so that you can filter it without capturing the entire standard output? Is there a way to reduce the amount of output, so that you only see the important events you care about?
If you really need to capture standard output and act on certain strings (events) of interest, then Win32 provides ways to do this, but I'd really take a hard look at whether this output can be modified to meet your needs before resorting to that.