Android Question Append text with ExternalStorage class

Wosl

Member
Dear All,

I'm using ExternalStorage https://www.b4x.com/android/forum/threads/externalstorage-access-sd-cards-and-usb-sticks.90238/ to store text data on my external device (SD card). This works as expected, when a new file is created and the content is written to it. But how can I append text to an existing file?

Wosl

Here is my sample code:
Write data to external device with ExternalStorage class:
#Region  Project Attributes
    #ApplicationLabel: SDCard
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
#AdditionalJar: androidx.legacy:legacy-support-core-utils
Sub Process_Globals
    Public Storage As ExternalStorage
End Sub
Sub Globals
End Sub
Sub Activity_Create(FirstTime As Boolean)
    '  Create a file on external device in preselected folder
    '  Output text to it
    '  Second Step: append additional text
    Private cCSV As String, cFileDir As String = "TestDir", cFileCSV As String = "Test.csv"
    Private cStoragePath As ExternalFile, extFile As ExternalFile, storedFile As ExternalFile
    Private DestinationFile As ExternalFile
    Private outputstream As OutputStream, inputstream As InputStream
    
    '  Storage initialization for external device
    Storage.Initialize (Me, "Storage")
    
    '  Wait until external system is available and call user prompt if not
    Storage.SelectDir(True)
    Wait For Storage_ExternalFolderAvailable
    
    '  Output file to external storage
    cStoragePath = Storage.Root
    extFile = Storage.FindDirOrCreate(cStoragePath, cFileDir)
    
    ' Find a file in selected folder and delete it if existing
    storedFile = Storage.FindFile(extFile,cFileCSV)
    If storedFile.IsInitialized = True Then
        Storage.DeleteFile(storedFile)
    End If

    '  Copy a string to inputstream
    cCSV = "Header1;Header2" & CRLF & "Value11;Value12" & CRLF & "Value21;Value22"
    inputstream = StringToInputStream (cCSV)
    
    '  Allocate a new file on external device
    DestinationFile = Storage.CreateNewFile(extFile,cFileCSV)
    outputstream    = Storage.OpenOutputStream(DestinationFile)
    
    '  Copy new file to external device
    File.Copy2(inputstream,outputstream)

    '  Close streams
    outputstream.Close
    inputstream.Close
    Log ("File '" & cFileCSV & "' created in folder '" & cFileDir & "'")
    Log ("Content of 'cCSV' written to File '" & cFileCSV & "'")
    
    '  Second step: add text to file
    cCSV = "Value31;Value32"
    '---------->  append data to existing file ????
    '  Close app
    Activity.Finish
    ExitApplication
End Sub
Sub StringToInputStream (s As String) As InputStream
    '  Copy string to inputstream
    Dim In As InputStream
    Dim data() As Byte = s.GetBytes("UTF8")
    In.InitializeFromBytesArray(data, 0, data.Length)
    Return In
End Sub
 

Wosl

Member
Thank you Erel,

perfect world - it works.

Here is the full code in order to help other B4X users managing data on external devices.

Append data to a file on external device using ExternalStorage class:
#Region  Project Attributes
    #ApplicationLabel: SDCard File Management
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
#AdditionalJar: androidx.legacy:legacy-support-core-utils
Sub Process_Globals
    Public Storage As ExternalStorage
End Sub
Sub Globals
End Sub
Sub Activity_Create(FirstTime As Boolean)
'##########################################################
'  Append data to a file on external device using ExternalStorage class
'  - Create a file on external device in preselected folder (here root)
'  - Output some text to it
'  - Append additional text to this file
'##########################################################
    Private cCSV As String, cFileDir As String = "TestDir", cFileCSV As String = "TestData.csv"
    Private cStoragePath As ExternalFile, extFile As ExternalFile, storedFile As ExternalFile
    Private DestinationFile As ExternalFile
    Private outputstream As OutputStream, inputstream As InputStream

'##########################################################
'  Initialization and test basic file operations
'##########################################################

    '  Storage initialization for external device
    Storage.Initialize (Me, "Storage")

    '  Wait until external system is available and call user prompt if not
    Storage.SelectDir(True)
    Wait For Storage_ExternalFolderAvailable

    '  Find a file on external storage or create it
    cStoragePath = Storage.Root
    extFile = Storage.FindDirOrCreate(cStoragePath, cFileDir)

    ' Find a file in selected folder and delete it if existing
    storedFile = Storage.FindFile(extFile,cFileCSV)
    If storedFile.IsInitialized = True Then
        Storage.DeleteFile(storedFile)
    End If

'##########################################################
'  Write data first time to external device
'##########################################################

    '  Copy a string to inputstream
    cCSV = "Header1;Header2" & CRLF & "Value11;Value12" & CRLF & "Value21;Value22"
    inputstream = StringToInputStream (cCSV)

    '  Allocate a new file on external device
    DestinationFile = Storage.CreateNewFile(extFile,cFileCSV)
    outputstream    = Storage.OpenOutputStream(DestinationFile)
    
    '  Copy new file to external device
    File.Copy2(inputstream,outputstream)

    '  Close streams
    outputstream.Close
    inputstream.Close

    Log ("File '" & cFileCSV & "' created in folder '" & cFileDir & "'")
    Log ("Content of 'cCSV' written to File '" & cFileCSV & "'")
    
'##########################################################
'  Append data to already existing file on external device
'##########################################################

    '  Copy a string to inputstream
    cCSV = CRLF & "Value31;Value32"
    inputstream  = StringToInputStream (cCSV)

    '  Open file on external device in append modus
    outputstream = OpenOutputStreamAppend(DestinationFile)

    '  Copy data to external device
    File.Copy2(inputstream,outputstream)

    '  Close streams
    outputstream.Close
    inputstream.Close

    Log ("Content of updated 'cCSV' appended to file '" & cFileCSV & "' in folder '" & cFileDir & "'")

    '  Close app
    Log ("Done")

    Activity.Finish
    ExitApplication
End Sub
Sub StringToInputStream (s As String) As InputStream
    '  Copy string to inputstream
    Dim In As InputStream
    Dim data() As Byte = s.GetBytes("UTF8")
    In.InitializeFromBytesArray(data, 0, data.Length)
    Return In
End Sub
Public Sub OpenOutputStreamAppend (EF As ExternalFile) As OutputStream
    '  Open outputstream in append modus
    Dim ctxt As JavaObject
    ctxt.InitializeContext
    Return ctxt.RunMethodJO("getContentResolver", Null).RunMethod("openOutputStream", Array(EF.Native.RunMethod("getUri", Null), "wa"))
End Sub

This sample code writes a new file with text data in the user selected directory on the external device. In a second step additional text will be appended to the now existing file. When you check the file with any file explorer, you'll see the expected content. I'll apply this code to store some large files (CSV formatted) in an app independent place on my external storage. If anybody has a better way to achieve this target, please let me know.

I hope that this code snippet will help other users to manage external files.

Let me add a wish, please. It would be useful if the append mode (3rd parameter) will be added to the ExternalStorage class similar to

OpenOutput:
File.OpenOutput(cDir, cFileName, True)

Best Regards and finally many thankx to Erel again
Wolf
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…