I am trying to write a program that allows for uses to traverse the contents of a SD card with buttons on a touch screen (assume there is only one level of files; aka no folders). However, I am finding it impossible to get a "list" of all the files on the SD card:
I can't just create an array of stringsor char* because I don't know the number
of files on the card. Besides, I want the container to be dynamic if
possible.
I can't create a vector because Arduino doesn't recognize std::vector
or vector even when I have C++ for Arduino.
Searching google produces new does not exist in Arduino's C++
I could use malloc (or new), but that would involve me creating my own container class. As interesting as that may be, the goal of what I am doing is not to implement a dynamic container class.
Have I missed something major in my search for such a function?
I recommend you look at my example MP3 File Player and the Web Player.
There are TWO issues:
1) You need to approach this from the point of view appreciating the Arduino does not have enough resources (SRAM) to hold a list of entire SdFAT's directories. Hence my approach was to use the users console for retaining the list. It dumps the directories contents to the console, along with a corresponding number. From which the user could select the number they wish to enter. Similarly the Web Player does the same thing, but when generating the HTML, it generates a link pointing to the corresponding listed item. Hence the list is stored on the console being either the Browser or Serial Monitor.
2) The default provided SD library is not sufficient to do what you want. Recently Arduino incorporated Bill Greiman’s SdFatLib as the under the hood class. But limited it. Where using Bill’s native SdFat library allows you the use of additional methods to access individual objects, such as getFilename(), not available in SD. This is necessary when going through the directory. The sd.ls(LS_DATE | LS_SIZE) will only dump directly to serial. Where you need to use access the individual files themselves. As show below or in actual code
SdFile file;
char filename[13];
sd.chdir("/",true);
uint16_t count = 1;
while (file.openNext(sd.vwd(),O_READ))
{
file.getFilename(filename);
Serial.print(count);
Serial.print(F(": "));
Serial.println(filename);
count++;
}
file.close();
Additionally there are buried public methods accessible by references as show in WebPlayer’s ListFiles() function, to get more discrete handling of the files.
Related
Being a beginner in C++, I found myself facing a problem when attempting to limit log file size using the ezlogger library: http://axter.com/ezlogger/
My take at it was to:
1) check log file size every n seconds
2) if size is too big, start logging to a second file (clearing it beforehand) Then switch between the files every n seconds.
I did 1. And I tackled 2 by changing the symlink used by the logging library as logging output file location (the app is running on Linux). However, it seems that the library retains a reference to the original file and never starts logging to the new file after changing the link.
The reason I decided to go this way was because I didn't want to touch the library. For an experienced programmer it would probably make more sense to somehow modify the library to enable switching log files. But with all the static variables and methods and hpp files containing actual code, I couldn't make sense of it and didn't know where to start.
So I guess I'm looking for opinions on my current approach, help with getting it to work and/or advice on how to do it differently/better.
Thanks.
Edit: I'm working on an existing older project which already uses ezlogger so I'd like to avoid using a different library if possible.
Either use logrotate (if you use unix like system) as it was suggested or modify your logging library. Those static variable you mention appear to be located in get_log_stream(). The modification would require checking on each get_log_stream call, the size of the current logging file. If the size exceeds some number of bytes then reopen stream. I don't see this logging library to be thread safe, so it probably isn't so you don't have to worry about it. But if your application is multithreaded then make a note of it.
The modification of get_log_stream would look as follows (its pseudocode):
// ...
if (logfile_is_open) {
if (logfile.tellp() > 1024*1024*10 /*10MB*/) {
logfile.close();
logfile.clear(); //clears flags
// TODO: update FileName accordingly, ie. add a count to it.
// TODO: remove older log files, etc.
logfile.open(FileName.c_str(), std::ios_base::out);
}
}
// Below is old code.
if (logfile_is_open) return logfile;
return std::cout;
I have a code in this format:
srcSAXController control(input_filename.c_str());
std::string output_filename = input_filename;
output_filename = "c-" + output_filename.erase(input_filename.rfind(XML_STR));
std:: ofstream myfile(output_filename.c_str());
coverage_handler handler(i == MAIN_POS ? true : false, output_filename);
control.parse(&handler);
myfile.write((char *)&control, sizeof(control));
myfile.close();
I want the content of object 'control' to be written into my file. How to fix the code above, so that content of the control object is written to the file.
In general you need much more than just writing the bytes of the object to be able to save and reload it.
The problem is named "serialization" and depending on a lot of factors there are several strategies.
For example it's important to know if you need to save and reload the object on the same system or if you may need to reload it on a different system; it's also fundamental to know if the object contains links to other objects, if the link graph is a simple tree or if there are possibly loops, if you need to support versioning etc. etc.
Writing the bytes to disk like the code is doing is not going to work even for something as simple as an object containing an std::string.
I want to delete first 10 files of the mounted drive. This drive is Unix system drive. I have written code which working fine for local drive but not mounted drive. Its deleting randomly but not sequentially. I have written code in MFC C++. Please Let me know if any one knows the solution. The code is like below.
char fileFound[256];
WIN32_FIND_DATA info;
HANDLE hp=INVALID_HANDLE_VALUE;
int count=10;
swprintf_s(fileFound,256,"%s\\*.*","G:\\foldername");
hp=FindFirstFile(fileFound,&info);
do
{
swprintf_s(fileFound,256,"%s\\%s","G:\foldername",info.cFileName);
DeleteFile(fileFound);
count--;
}while(FindNextFile(hp,&info)&&count);
FindClose(hp);
Its deleting randomly but not sequentially.
This behavior is documented:
[...] FindFirstFile does no sorting of the search results.
As well as here:
The order in which the search returns the files, such as alphabetical order, is not guaranteed, and is dependent on the file system. If the data must be sorted, the application must do the ordering after obtaining all the results.
If you need to delete the first n files from a set of files, you need to gather the entire set of files, sort the set based on an arbitrary predicate, and then perform an action on the first n items.
I'm making a simple bug tracker and am using a text file as the database. Right now I'm reading in all the information through keys and importing them into specific arrays.
for (int i = 0; i < 5; i++)
{
getline(bugDB, title[i], '#');
getline(bugDB, importance[i], '!');
getline(bugDB, type[i], '$');
getline(bugDB, description[i], '*');
}
Here is what's in my (terribly unreadable) file
Cant jump#Moderate!Bug$Every time I enter the cave of doom, I'm unable
to jump.*Horse too expensive#Moderate!Improvement$The horses cost way
too much gold, please lower the costs.*Crash on startup#Severe!Bug$I'm
crashing on startup on my Win8.1 machine, seems to be a 8.1
bug.*Floating tree at Imperial March#Minimal!Bug$There is a tree
floating about half a foot over the ground near the crafting
area.*Allow us to instance our group#Moderate!Improvement$We would
like a feature that gives us the ability to play with our groups alone
inside dungeons.*
Output:
This works great for me, but I'd like to be able to delete specific bugs. I'd be able to do this by letting the user choose a bug by number, find the corresponding * key, and delete all information until the program reaches the next * key.
I'd appreciate any suggestions, I don't know where to start here.
There is no direct mechanism for deleting some chunk of data from the middle of the file, no delete(file, start, end) function. To perform such a deletion you have to move the data which appears after the region; To delete ten bytes from the middle of a file you'd have to move all of the subsequent bytes back ten, looping over the data, then truncate to make the file ten bytes smaller.
In your case however, you've already written code to parse the file into memory, populating your arrays. Why not just implement a function to write the contents of the arrays back to a file? Truncate the file (open in mode "w" rather than "w+"), loop over the arrays writing their contents back to the file in your preferred format, but skip the entry that you want to delete.
its only possible by manually copying the data from input file to output file and leaving out the entry you want to delete.
but: i strongly encourage the usage of some small database for keeping the informations (look at sqlite)
Also its a bad bugtracker if solving the bug means "delete it from database" (its not even is a tracker). give it a status field (open, refused, duplicate, fixed, working, ...).
Additional remarks:
use one array that keeps some structure with n informations and not n arrays.
please remind that someone may use your delimiter characters in the descriptions (use some uncommon character and replace its usage in saved text)
explanation for 1.:
instead of using
std::vector<std::string> title;
std::vector<int> importance;
std::vector<std::string> description;
define a structure or class and create a vector of this structure.
struct Bug{
std::string title;
int importance; // better define an enum for importance
std::string description;
};
std::vector<Bug> bugs;
I created a .properties file that contains a few simple key = value pairs.
I tried it out from a sample c++ console application, using imported java classes, and I was able to access it, no problem.
Now, I am trying to use it in the same way, from a C++ dll, which is being called by another (unmanaged) c++ project.
For some reason, the file is not being accessed.
Maybe my file location is wrong. Where should I be storing it?
What else might be the issue?
TIA
As you are mentioning "DLL" i guess, that you are using MS Windows. Finding a file there from a DLL, and independently from the logged on user is a restricted item. The best way is to store the file in a path assembled from the environment variable ALLUSERSPROFILE. This is the only location that is equal to all users and where all users usually have write access. Your applications data should reside in a private subdirectory named like < MyCompany > or < MyApplicationsName >. Type
echo %ALLUSERSPROFILE%
on a windows command line prompt to find out the actual location on a machine.
Store your data in i.e.:
%ALLUSERSPROFILE%\MyApp\
Your dll can then query the location of ALLUSERSPROFILE using getenv:
char *allUsersData = getenv("ALLUSERSPROFILE");