0

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());
 }
}
Codebreaker007
1,3311 gold badge7 silver badges14 bronze badges
asked Apr 30, 2020 at 8:22
2
  • 1
    Try it with /DATA/test.txt I remember SD library uses the classic 8.3 filenames and data_test.txt is invalid Commented Apr 30, 2020 at 8:48
  • @DataFiddler I'm using SdFat.h with Long Names (which allows names up to 255 characters) Commented Apr 30, 2020 at 9:14

2 Answers 2

1

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.

answered Apr 30, 2020 at 19:13
0

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);
 }
}
answered Apr 30, 2020 at 9:02
9
  • 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? Commented 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. Commented 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 subdirectory Commented 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 necessary Commented 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) Commented Apr 30, 2020 at 14:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.