jumperless-boardboard-v5/RP23V50firmware/CodeDocs/JFS_Module_Documentation.md

8.1 KiB

JFS (Jumperless FileSystem) Module

The jfs module is basically like MicroPython's vfs and parts of os, but kinda written in a style that's probably more familiar to Arduino-style C++ people (me). It uses the almost standardized API shared by FatFS (the one Jumperless actually uses), LittleFS, and SDFS, but still has been Pythonified to use types that are easier to work with in MicroPython.

Module Usage

To use the module, import it like any other Python module:

import jfs  #you don't actually need this, jfs is imported globally by default

# List files in the root directory
files = jfs.listdir('/')   # returns a python list
print(files)

Output:

['config.txt', 'nodeFileSlot0.txt', 'python_scripts/', 'nodeFileSlot1.txt', 'nodeFileSlot2.txt', 'nodeFileSlot3.txt', 'nodeFileSlot4.txt', 'nodeFileSlot5.txt', 'nodeFileSlot6.txt', 'nodeFileSlot7.txt', 'net_colors/']
If you want to make this print with subdirectories
files = jfs.listdir('/')

for file in range(len(files)):

    print(files[file])

    if files[file].endswith("/"):
        subdir = jfs.listdir(files[file])

        for i in range(len(subdir)):
            print("     - " + subdir[i])

Output:

nodeFileSlot0.txt
python_scripts/
     - history.txt
     - examples/
     - fake_gpio.py
     - _temp_repl_edit.py
     - Hey.txt
     - script_1.py
     - script_2.py
     - script_3.py
     - log.txt
     - lib/
     - script_4.py
     - pathtest.py
nodeFileSlot1.txt
nodeFileSlot2.txt
nodeFileSlot3.txt
nodeFileSlot4.txt
nodeFileSlot5.txt
nodeFileSlot6.txt
nodeFileSlot7.txt
net_colors/
    - netColorsSlot0.txt

File API

File objects returned by jfs.open() support method calls directly on the object:

# Object-oriented file operations

# Write-only mode
f = jfs.open('hello.txt', 'w')
f.write('Hello, Jumperless!')
f.close()

# Read from the file (need to reopen or use w+/r+ mode)
f = jfs.open('hello.txt', 'r')
content = f.read()             # Read from file object
size = f.size()                # Get file size
f.close()

# Read-write mode (truncates file)
f = jfs.open('hello.txt', 'w+')
f.write('Hello, Jumperless!')
f.seek(0)                      # Seek to beginning to read what we wrote
content = f.read()             # Now this works!
f.close()

# Context manager support (automatically closes file)
with jfs.open('data.txt', 'w+') as f:
    f.write('This file will be automatically closed')
    f.seek(0)                  # Reset to beginning
    content = f.read()         # Read back what we wrote
    pos = f.tell()             # Get current position
    name = f.name()            # Get file name
Other ways to do the same thing

2. Module-Level Functions

You can also use module-level functions with file handles:

f = jfs.open('hello.txt', 'w')
jfs.write(f, 'Hello, Jumperless!')  # Module-level function
jfs.seek(f, 0)                      # Module-level function  
content = jfs.read(f)               # Module-level function
jfs.close(f)                        # Module-level function

3. Direct String Operations (For simple cases)

# Write/read entire files at once (no file handles needed)
jfs.write('config.txt', 'key=value\nother=setting')
content = jfs.read('config.txt')

File Modes

When using jfs.open(path, mode), the following modes are supported:

Mode Description Read Write Create
'r' Read only
'w' Write only
'a' Append only
'r+' Read + Write
'w+' Read + Write
'a+' Read + Append

Important: You cannot read from a file opened in write-only mode ('w' or 'a'). Use 'w+', 'r+', or 'a+' if you need both read and write access.

Open a file for writing

f = jfs.open('hello.txt', 'w')
f.write('Hello, Jumperless!')  # Now works with object-oriented API!
f.close()

Directory Operations

jfs.listdir(path)

Returns a list containing the names of the entries in the directory given by path.

  • path (str): The path to the directory.

Example:

# List contents of the root directory
print(jfs.listdir('/'))

# List contents of a subdirectory
jfs.mkdir('/my_dir')
print(jfs.listdir('/my_dir'))

jfs.mkdir(path)

Create a new directory.

  • path (str): The path of the new directory.

jfs.rmdir(path)

Remove an empty directory.

  • path (str): The path of the directory to remove.

jfs.remove(path)

Remove a file.

  • path (str): The path of the file to remove.

jfs.rename(old_path, new_path)

Rename a file or directory.

  • old_path (str): The current path.
  • new_path (str): The new path.

jfs.exists(path)

Check if a file or directory exists.

  • path (str): The path to check.
  • Returns True if it exists, False otherwise.

jfs.stat(path)

Get status of a file or directory.

  • path (str): The path of the file or directory.
  • Returns a tuple with file information (mode, size, etc.), similar to os.stat().

Filesystem Information

jfs.info()

Get information about the filesystem.

  • Returns a tuple (total_bytes, used_bytes, free_bytes).

Example:

total, used, free = jfs.info()
print("Filesystem Size: " + str(total / 1024) + " KB")
print("Used: " + str(used / 1024) + " KB")
print("Free: " + str(free / 1024) + " KB")

File I/O

The jfs module supports standard file opening and handling using jfs.open() and file objects, including support for the with statement for automatic resource management.

jfs.open(path, mode='r')

Open a file and return a corresponding file object.

  • path (str): The path to the file.
  • mode (str, optional): The mode in which the file is opened. Defaults to 'r'.
    • 'r': Read (default).
    • 'w': Write (creates a new file or truncates an existing one).
    • 'a': Append.
    • 'r+': Read and write.
    • 'w+': Write and read (creates/truncates).
    • 'a+': Append and read.

Example:

# Open a file for reading
f = jfs.open('config.txt', 'r')
content = f.read()
f.close()

# Use 'with' for automatic closing
with jfs.open('data.log', 'a') as log_file:
    log_file.write('New log entry.\\n')

File Object Methods

The file object returned by jfs.open() has the following methods:

file.read([size])

Read size bytes from the file. If size is omitted or negative, the entire file is read.

file.write(data)

Write the given string or bytes data to the file. Returns the number of bytes written.

file.close()

Close the file. A closed file cannot be read or written to.

file.seek(offset, [whence])

Change the stream position.

  • offset: The byte offset.
  • whence (optional):
    • 0: Seek from the start of the stream (default). Use jfs.SEEK_SET.
    • 1: Seek from the current position. Use jfs.SEEK_CUR.
    • 2: Seek from the end of the stream. Use jfs.SEEK_END.

file.tell()

Return the current stream position.

  • Aliases: file.position()

file.size()

Return the total size of the file in bytes.

file.available()

Return the number of bytes available to be read from the current position to the end of the file.

file.name

Returns the name of the file.


Module-Level File Operations

For convenience, the jfs module also provides functions that operate directly on file handles returned by jfs.open(). This can be useful in some scripting scenarios but using file object methods is generally preferred for clarity.

  • jfs.read(file_handle, [size])
  • jfs.write(file_handle, data)
  • jfs.close(file_handle)
  • jfs.seek(file_handle, offset, [whence])
  • jfs.tell(file_handle)
  • jfs.size(file_handle)
  • jfs.available(file_handle)

Example:

file_handle = jfs.open('temp.txt', 'w')
jfs.write(file_handle, 'some data')
jfs.close(file_handle)