I'm using the SdFat.h library on a STM32 and I can successfully create a file in the root directory using SD.open("test.txt", FILE_WRITE); but my code fails to create SD.open("DATA/data_test.txt", FILE_WRITE); in a directory. Here's the piece of code that successfully creates a file in the root:
String final_book_name = upload_book_name + ".txt";
if (SD.exists(final_book_name.c_str())) {
SD.remove(final_book_name.c_str());
}
tft.println(final_book_name); // This successfully prints "test.txt"
book_file = SD.open(final_book_name, FILE_WRITE);
if (SD.exists(final_book_name.c_str())) {
tft.print("Created file");
} else {
tft.print("Failed to create/replace\nfile!");
}
and here's the piece of the code that fails to create a file in a directory:
if (!SD.exists(DATA_DIR)) {
SD.mkdir(DATA_DIR);
}
String final_book_name = upload_book_name + ".txt";
String book_data_path = DATA_DIR;
book_data_path += "/data_" + final_book_name;
if (SD.exists(book_data_path.c_str())) {
SD.remove(book_data_path.c_str());
}
tft.println(book_data_path); // This successfully prints "DATA/data_test.txt"
File book_data_file = SD.open(book_data_path, FILE_WRITE);
if (SD.exists(book_data_path.c_str())) {
book_data_file.print(upload_book_font);
book_data_file.print("|");
book_data_file.print("0");
book_data_file.close();
} else{
tft.print("Failed to create/replace\ndata file!");
if (SD.exists(final_book_name.c_str())) {
SD.remove(final_book_name.c_str());
}
}
2 Answers 2
I found the issue. I'm not creating the directory folder properly. When I checked the SD card from another device, the DATA folder was invalid, and creating it manually works. I'll look for a solution and post an update.
UPDATE: https://forum.arduino.cc/index.php?topic=421131.0 I'll try this tomorrow but it'll probably fix the issue.
As you have given no variable for DATA_DIR
String book_data_path = DATA_DIR;
book_data_path += "/data_" + final_book_name;
so your resulting path looks like
DATA_DIR + "/data_" + final_book_name
IF DATA_DIR = "/"
then it would be "/" + "/data_" + final_book_name
As tip do not use the string class but char arrays
definition
const char[] DATA_DIR = "/books";
char book_data_path [128] = {'0円'};
char final_book_name [13] = {'0円'}; // IF no LFN support is used its 8.3 !!!
const char upload_book_name[] = "my_book";
strcpy (final_book_name, upload_book_name);
strcat (final_book_name, ".txt");
Serial.println(final_book_name);
If you want long filr namesupport us SDFat library or enable LFB withSD lib (whichneeds about 35% ,ore memory as SDfat (when using long file names).
EDIT
As you are using SDFat and I do not know which version/fork there is abug with writing to subdirectories. Please check the following:
To check run the SdFat\examples\DirectoryFunctions
and watch your serial monitor for the results
SdFile.cpp. At line 782 and 1452, you have (in my version):
if (block <= m_vol->cacheBlockNumber()
&& block < (m_vol->cacheBlockNumber() + nb)) {
The working code has:
if (m_vol->cacheBlockNumber() <= block
&& block < (m_vol->cacheBlockNumber() + nBlock)) {
If you have the upper version change it and it should work
EDIT 2 Work around for buggy SDFat lib
Here is a workaround code
const char DATA_DIR [] = "data";
char final_book_name[128] ={'0円'};
char book_data_path [256] ={'0円'};
if (!SD.exists(DATA_DIR)) {
SD.mkdir(DATA_DIR);
SD.chdir(DATA_DIR);
}
strcpy (final_book_name, upload_book_name);
strcat (final_book_name, ".txt";
String book_data_path = DATA_DIR;
strcpy(book_data_path, "data_");
strcat(book_data_path, final_book_name);
if (SD.exists(book_data_path)) {
SD.remove(book_data_path);
}
SD.mkdir(book_data_path);
SD.chdir(book_data_path);
tft.println(DATA_DIR);
tft.println(book_data_path); // This successfully prints "DATA/data_test.txt"
File book_data_file = SD.open(final_book_name, FILE_WRITE);
if (SD.exists(final_book_name)) {
book_data_file.print(upload_book_font);
book_data_file.print("|");
book_data_file.print("0");
book_data_file.close();
} else{
tft.print("Failed to create/replace\ndata file!");
if (SD.exists(final_book_name)) {
SD.remove(final_book_name);
}
}
-
DATA_DIR is "DATA". I don't see the solution in your answer. I will make my Strings to characters, that's a good idea but what about my main issue here?JingleBells– JingleBells2020年04月30日 10:55:01 +00:00Commented Apr 30, 2020 at 10:55
-
Sorry, it's still unclear to me what I should do. I'm using STM32, not an Arduino and I don't have a Serial Monitor. I will try downloading a newer SdFat version.JingleBells– JingleBells2020年04月30日 13:48:50 +00:00Commented Apr 30, 2020 at 13:48
-
I downloaded the newest version of SdFat from here: github.com/greiman/SdFat and ran it, but it still fails to create a file in a subdirectoryJingleBells– JingleBells2020年04月30日 14:29:09 +00:00Commented Apr 30, 2020 at 14:29
-
I could try to do SD.chdir(DATA_DIR); but I'm not sure how that works exactly and if even that's the problem. I don't think SD.chdir(DATA_DIR); is necessaryJingleBells– JingleBells2020年04月30日 14:43:49 +00:00Commented Apr 30, 2020 at 14:43
-
I tried with SD.chdir(DATA_DIR); (as far as I know how to use it) but it failed. (it created the file in the root, not in the dir)JingleBells– JingleBells2020年04月30日 14:58:15 +00:00Commented Apr 30, 2020 at 14:58
/DATA/test.txt
I remember SD library uses the classic 8.3 filenames anddata_test.txt
is invalid