Example for creating a file and doing something with it

gui
#1

I want to save four strings in a file and use it later. I had looked the documents, but still not konw which function to chose for sure. The InputStream(), CreateFile() or other ways to create file?
Thanks in advance.

1 Like

#2

Like with the whole JUCE Library, it’s pretty simple once you wrap your head around it.

First off you have to create a File object. I usually create them on the Stack, so you would do something like this:

File resourceFile ("/absolute/path/to/file.txt");

If you wanted to rather use a relative path, you can do that too:

File resourceFile = File::getCurrentWorkingDirectory().getChildFile ("file.txt");

After you have done this, you can then check if the file exists, as the File object merely holds a path and no data from the file itself in it:

if (! resourceFile.existsAsFile())
{
    DBG ("File doesn't exist ...");
}

// ... Rest of your code

Now you want to read the file. For that create a new FileInputStream:

unique_ptr<FileInputStream> input (resourceFile.createInputStream());

if (! input->openedOk())
{
    DBG("Failed to open file");
    // ... Error handling here
}
    
bool readWholeFile = true;
if (readWholeFile)
{
    String content = input->readString();
    // ... Do your stuff. New lines are normally seperated by "\n"
}
else
{
    while (! input->isExhausted())
    {
        String singleLine = input->readNextLine();
        // ... Do something with each line
    }
}

Now resourceString contains your textfile with each line sperated by a newline character "\n".

If you wanted to write a String to a file, you would use a FileOutputStream and I would also advise you to use a TemporaryFile:

TemporaryFile tempFile (resourceFile);

FileOutputStream output (tempFile.getFile());

if (! output.openedOk())
{
    DBG ("FileOutputStream didn't open correctly ...");
    // ... some other error handling
}
    
output->setNewLineString("\n");

output->writeText("Some text");

output.flush(); // (called explicitly to force an fsync on posix)

if (output.getStatus().failed())
{
    DBG ("An error occurred in the FileOutputStream");
    // ... some other error handling
}

bool success = tempFile.overwriteTargetFileWithTemporary();
3 Likes

#3

Thank you so much:+1::grinning:

0 Likes

#4

No problem. Hopes this helps other beginners too

1 Like

#5

Yes, this is very helpful for beginners.

0 Likes

#6

Thanks DustVoice, hopes this helps other beginners like me.:slightly_smiling_face:

0 Likes

#7

It can actually be a lot simpler if you don’t worry too much about error cases

juce::File::getCurrentWorkingDirectory()
                    .getChildFile ("file.txt")
                    .replaceWithText ("your text");

But when you say you “want to save four strings in a file”, that’s probably the wrong way to think about it. You should probably be storing some properties as XML or JSON in the file, not just writing raw text directly.

1 Like

#8

Yes, you are right. I will try more correct ways to operate with file or other parts in juce the following day.
Thank you so much.
This forum is very helpful, I learned a lot with the help of other jucer.

0 Likes

#9

By the way, how can I clear the file and make it empty, so that I can save new strings? Thanks in advance.

0 Likes

#10

Well, File::replaceWithText() does what it says on the tin.
As well as a hundred other ways to do it, e.g. XmlElement::writeToFile

0 Likes

#11

I had used File::replaceWithText(),but it did not work. After use this function, the “test.txt” still has the string I had append last time.

0 Likes

#12

It’s time for you to learn how to debug :slight_smile:

add some breakpoints, step through the code, see what is not doing what you expect it to do.

0 Likes

#13

Yes, I had doing it almost whole afternoon, but still can’t find out where is wrong.:disappointed_relieved:

0 Likes

#14

@kangkang this only works if the file exists.

File f = juce::File::getCurrentWorkingDirectory() .getChildFile (“file.txt”);
if( !f.existsAsFile() )
{
    auto result = f.create();   
    if( !result.wasOk() )
    {
        DBG( "failed creating file!" );
        jassertfalse; //pause so we can see the error message
        return;  //bail 
    }
}

f.replaceWithText("your text"); //good to go!
0 Likes

#15

Here is my code:


When I use the function replacewithtext(), it doesn’t work

0 Likes

#16

No… that’s FAKE NEWS. The file does not need to exist.

Most likely you were just trying to create it in a folder that doesn’t exist, or which doesn’t have permission or something.

0 Likes

#17

getChildFile() creates a file if it doesn’t exist? :thinking::thinking::thinking:
Or does replaceWithText() create a file if it doesn’t exist?

0 Likes

#18

File is just a location in the filesystem, it doesn’t need to exist to make File valid.

replaceWithText() will end up here:

…so yes, the file is created (by moving the tempFile here). The whole point of using the TempFile internally is to make the writing an atomic operation (by swapping the file descriptor rather than opening file, writing writing writing, closing)

I personally would ignore that and resort to FileOutputStream, that is much more versatile:

auto file = juce::File::getCurrentWorkingDirectory().getChildFile ("file.txt");
FileOutputStream output (file);
if (output.openedOk())
{
    output.setPosition (0);  // default would append
    output.truncate();
    output.write ("whatever");
}

This has all the overloads available for whatever you want to write: OutputStream::write() ff.

1 Like