Android Tutorial Text files

Many applications require access to a persistent storage. The two most common storage types are files and databases.
We will cover text files in this tutorial.

The predefined Files object has several utility methods for working with text files which are pretty easy to use.

Files locations - There are several important locations where you can read or write files.

File.DirAssets
The assets folder includes the files that were added with the file manager. These files are read-only. You can not create new files in this folder (which is actually located inside the apk file).

File.DirInternal / File.DirInternalCache
These two folders are stored in the main memory and are private to your application. Other applications cannot access these files.
The cache folder may get deleted by the OS if it needs more space.

File.DirRootExternal
The storage card root folder.

File.DirDefaultExternal
The default folder for your application in the SD card.
The folder is: <storage card>/Android/data/<package>/files/
It will be created if required.

Note that calling any of the two above properties will add the EXTERNAL_STORAGE permission to your application.

Tip: You can check if there is a storage card and whether it is available with File.ExternalReadable and File.ExternalWritable.

The predefined File object (predefined means that you do not need to declare it yourself) includes several methods for writing and reading to files.
You can also use TextReader and TextWriter to do it manually.
Note that TextReader and TextWriter are not limited to files and can work with other streams.

TextReader and TextWriter have an advantage over the File read/write methods when working with large files. The File methods read the file completely and store its content in memory. In many cases this is the most convenient solution, however if you work with large files (more than 1-2mb) you may prefer to work with TextReader or TextWriter.

File.WriteString - Writes the given text to a new file.
File.ReadString - Reads a file and returns it content as a string.
File.WriteList - Writes all values stored in a list to a file. All values are converted to string type if required. Each value will be stored in its own line.
Note that if a value contains the new line character it will saved over more than one line and when you read it, it will be read as multiple items.
File.ReadList - Reads a file and stores each line as an item in a list.
File.WriteMap - Takes a map object which holds pairs of key and value elements and stores it in a text file. The file format is known as Java Properties file: .properties - Wikipedia, the free encyclopedia
The file format is not too important unless the file is supposed to be edited manually. This format makes it easy to edit it manually.
One common usage of File.WriteMap is to save a map of "settings" to a file.
File.ReadMap - Reads a properties file and returns its key/value pairs as a Map object. Note that the order of entries returned might be different than the original order.

Example:
B4X:
Sub Process_Globals

End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    If File.ExternalWritable = False Then
        Msgbox("Cannot write on storage card.", "")
        Return
    End If
    SaveStringExample
    ReadStringExample
    
    WriteListExample
    ReadListExample
    
    WriteMapExample
    ReadMapExample
    
    WriteTextWriter
    ReadTextReader
End Sub

Sub SaveStringExample
    File.WriteString(File.DirRootExternal, "String.txt", _
        "This is some string" & CRLF & "and this is another one.")
End Sub

Sub ReadStringExample
    Msgbox(File.ReadString(File.DirRootExternal, "String.txt"), "")
End Sub

Sub WriteListExample
    Dim List1 As List
    List1.Initialize
    For i = 1 To 100
        List1.Add(i)
    Next
    File.WriteList(File.DirRootExternal, "List.txt", List1)
End Sub

Sub ReadListExample
    Dim List1 As List
    'We are not initializing the list because it just holds the list that returns from File.ReadList
    List1 = File.ReadList(File.DirRootExternal, "List.txt")
    Msgbox("List1.Size = " & List1.Size & CRLF & "The third item is: " & List1.Get(2), "")
End Sub

Sub WriteMapExample
    Dim Map1 As Map
    Map1.Initialize
    For i = 1 To 10
        Map1.Put("Key" & i, "Value" & i)
    Next
    File.WriteMap(File.DirRootExternal, "Map.txt", Map1)
End Sub

Sub ReadMapExample
    Dim Map1 As Map
    'Again we are not initializing the map.
    Map1 = File.ReadMap(File.DirRootExternal, "Map.txt")
    'Append all entries to a string builder
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("The map entries are:").Append(CRLF)
    For i = 0 To Map1.Size - 1
        sb.Append("Key = ").Append(Map1.GetKeyAt(i)).Append(", Value = ")
        sb.Append(Map1.GetValueAt(i)).Append(CRLF)
    Next
    Msgbox(sb.ToString,"")
End Sub

Sub WriteTextWriter
    Dim TextWriter1 As TextWriter
    TextWriter1.Initialize(File.OpenOutput(File.DirRootExternal, "Text.txt", False))
    For i = 1 To 10
        TextWriter1.WriteLine("Line" & i)
    Next
    TextWriter1.Close
End Sub

Sub ReadTextReader
    Dim TextReader1 As TextReader
    TextReader1.Initialize(File.OpenInput(File.DirRootExternal, "Text.txt"))
    Dim line As String
    line = TextReader1.ReadLine    
    Do While line <> Null
        Log(line) 'write the line to LogCat
        line = TextReader1.ReadLine
    Loop
    TextReader1.Close
End Sub
 

klaus

Expert
Licensed User
Hi Sarah,
There is an example here: add imageview half manually

The program loads image files from a folder and shows them in a ScrollView with ImageViews.
In the code you should either choose the right code line for the folder you want or change one line with your folder.
B4X:
[FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2]bmpImage.Initialize([/SIZE][/FONT][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff][FONT=Courier New][SIZE=2][COLOR=#0000ff][FONT=Courier New][SIZE=2][COLOR=#0000ff]File[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2].DirAssets,[/SIZE][/FONT][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000]"Image"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2]&i&[/SIZE][/FONT][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000][FONT=Courier New][SIZE=2][COLOR=#800000]".jpg"[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][FONT=Courier New][SIZE=2])[/SIZE][/FONT]
[/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#008000][FONT=Courier New][SIZE=2][COLOR=#008000][FONT=Courier New][SIZE=2][COLOR=#008000]' bmpImage.Initialize(File.DirInternal,"Image"&i&".jpg")[/COLOR][/SIZE][/FONT]
[SIZE=2][FONT=Courier New][COLOR=#008000]' bmpImage.Initialize(File.DirDefaultExternal,"Image"&i&".jpg")[/COLOR][/FONT][/SIZE][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
The default folder is in the program is File.DirAssets.

Best regards.
 

Gearcam

Active Member
Licensed User
Dir list and select text file to open

I want to be able to list the text files in a perticular dir on the SD card (not downloaded with app) then scroll down them, select one in list view and open it.

I can do the opening etc but how do you read a directory with all the files in it ?

thanks

Steve
 

alexb

Member
Licensed User
Cannot compile example

Hi Erol,

thanks for this great product and your outstanding support!

I have a quick question, for some unknown reason I cannot compile the example that you have posted to test the different file read/write functions. I copied and pasted it into a new project but when compiling I get the error message shown in the attached screenshot. Note: I do not have such error with any other project so far and I downloaded and tested quite a lot.

Btw: Is there anywhere a function such as 'GetProfileString/WriteProfileString' allowing to read/write valuenames/values in a given[SectionName] of a txt file?

Thanks for your help in advance!

alex
 

Attachments

  • Error Android Manifest.png
    Error Android Manifest.png
    18.6 KB · Views: 524

alexb

Member
Licensed User
Compilation issue solved

Oh, I think the compilation works now. After I deleted virtually all the source code I still had the problem, so had to be something in the header I thought. It turned then out that I do not get the compiler error message when changing the Aplication label from 'FileRead&Write" to simply 'FileReadWrite'. Didn't know that '&' sign is not allowed.

Anyway, could you reply to my 2nd question (Read/WriteProfileString).

Thank you!

alex
 

alexb

Member
Licensed User
... writing to a different section

Dear Erel, thanks for taking time to look at this!

I intend to use a script file for controlling some operations of the program that I am working on. A user or myself will then later be able to simply change the script to change the program behaviour rather than hardcoding customizations. So the script file will be a lot more complex than a simple INI file with a few keys and values to read/write for program initialization. Structurally this could look like this:

[ActionSection1]
Action1=DoThisThat
Action2=DoThisThat2
etc.

or simplier (but not preferred)
[ActionSection2]
DoThisThat
DoThisThat2

The use of sections makes it easier to read, understand and modify the script file.

For writing/reading such sections I have used in the past commands similar to the following:

ReadProfileString("MyScriptFile.INI", "ActionSection1", "Action1", %ActionToDo%)

or

WriteProfileString ("MyScriptFile.INI", "ActionSection1", "Action1", "DoThisThat")

I wonder if there exists anything as simple as this under B4A or how it could be emulated best. My understanding is that with WriteMap/ReadMap I can manipulate pairs of Keynames & Values whereas I require a 'third dimension' with the sections:
[SectionName]
Key/Valuename=Value

I believe other users might be interested in such a funcitonality as well, maybe not for a script file but for better readability of INI files. If a new library is required for doing this I am afraid my skills won't allow me to write and provide such a library.

Thanks for your attention.

alex
 

alexb

Member
Licensed User
Thanks for your reply Erel!

I am thinking about using RandomAccessFile.Read/WriteObject as you suggest but wouldn't I loose the capability of easily modifying the script file if I use a binary file as input file? Is there anywhere an example of writing/reading a user defined type or could you illustrate using my Read/WriteProfileString example as a starting point?

Thank you, alex
 

alexb

Member
Licensed User
Erel, I have decided to use TextReader for creating my ReadProfileString functionality:

'This returns the contents of the whole section (regardless whether the section contains just lines or pairs of keys/values)
ReturnValue = ReadProfileString(File.DirAssets,"INIFILE.INI","Section3","")

'This returns only the specified line #4 (= 5th line) within the section. Lines starting with a comment ';' or empty lines are ignored
ReturnValue = ReadProfileString(File.DirAssets,"INIFILE.INI","Section3","4")

'This returns the value matching the specified key
ReturnValue = ReadProfileString(File.DirAssets,"INIFILE.INI","Section2","Key_desc4")

I hope I caught all/most of the possible error conditions:
'Error 00 = section not found and EOF (defined by [End] section)
'Error 01 = key exists but no value assigned (missing value)
'Error 02 = key exists but no value assigned (missing '=' sign)
'Error 03 = section exists but key not found
'Error 04 = section name not found
'Error 05 = empty section
'Error 06 = invalid line number!

This is not rocket science but maybe it's useful for some others, so I post it here.

Certainly it's not economical to open/close every time the file for reading just a value, a line or a section - in particular if the file is big. I would prefer to open the file once, load the contents to memory and work from there. But don't know how to do that. Any comments, hints on errors and improvements welcome.

alex
 

Attachments

  • ReadProfileString 1.0.zip
    6.9 KB · Views: 705

Mickego

Member
Licensed User
Here is a ini.bas handling INI file Write/Read

I made a quick and dirty ini.bas that handle my needs
maybe someone else can use it.

(Info C&P from bas-file)
###################################################

' Functions to Read and Write ini-file from Activity

' ini.writeini(File.DirDefaultExternal,"test.ini","Section 1","TestKey1","Sunday")
' ini.writeini(File.DirDefaultExternal,"test.ini","Section 1","TestKey2","Monday")
' ini.writeini(File.DirDefaultExternal,"test.ini","Section 2","TestKey1","Tuesday")
' ini.writeini(File.DirDefaultExternal,"test.ini","Section 2","TestKey2","Wednesday")
' Creates this
'
' (File test.ini)
' [Section 1]
' TestKey1=Sunday
' TestKey2=Monday
' [Section 2]
' TestKey1=Tuesday
' TestKey2=Wednesday
'
' To read 1 of above Keys into variable 'str'
' str = ini.readini(File.DirDefaultExternal,"test.ini","Section 1","TestKey1")
' str will be set to Sunday
' ################################################


No error handling,

Simply return "" if not actual "Section-Key:Value" exist

rgds Mickego
 

Attachments

  • ini.bas
    3.1 KB · Views: 593

margret

Well-Known Member
Licensed User
Read & write to data files

I am new to B4A and I have no knowledge of how to work with data files. I have looked and read through the samples and I am still lost. I have been programming for 20+ years but in database apps like Foxpro, dbase, etc. I also have written many programs in gwbasic and understand that fine. I am looking for help to use B4A like dbase. I would like to have fields like name, address, zip, etc. in one record. I would like to be able to pull like the address from record 30 for example. I would also like to have a one record file that may have 30 different fields(varibles) in it. Any help would be great. I have been working on my first app and have all the menus and inputs working fine. The form designer works great, now I just need to know how to read/write the data to files and how to control where the files are written(path or directory). I really don't want them on the SDCard.

Thanks for any help.
Margret
 

zouriteman

Member
Licensed User
ReadList

EREL ,

why ReadList , with a non-existing file , does not start a runtime error ?

and does not initialize the string list with ZERO items ?


In my mine , this is a bug ?
 

Carol

Member
Licensed User
Redirect file loading link

Hi all, I am trying out the file reading example on the following link
Files - Basic4android Wiki
on my Asus android pad and so far I've not been able to successfully read the file since the File.DirRootExternal is /mnt/sdcard but the file exists in external_sd folder. Apprently, File.[location] there is no location that points to external_sd folder. Is there a way to directly specify the folder? thanks a lot.
 

Carol

Member
Licensed User
hmm how about from
/mnt/sdcard to
/mnt/external_sd?

May I ask how I can do that?
Thank you very much!
 
Top