Probably, it is normal (from FileWrite's point of view) to append yet another crlf to the end of a string each time it saves it. A simple test demonstrates such behaviour (open "some.txt" in NotePad++, play Bonham's 'Moby Dick' on "Open" and "Save" buttons and see how the trail of crlfs grows):
B4X:
Sub cmdOpen_Click
ErrorLabel(errFO)
FileOpen(c1,"some.txt",cRead)
a = FileReadToEnd(c1)
FileClose(c1)
Return
errFO:
Msgbox("Can't open it, dude!")
End Sub
Sub cmdSave_Click
ErrorLabel(errFS)
FileOpen(c1,"some.txt",cWrite)
FileWrite(c1,a)
FileClose(c1)
Return
errFS:
Msgbox("Can't save it, dude!")
End Sub
If my code is wrong, what's the right code? Else, what's the most elegant (resource-saving) technique to trim crlf (during or after each save)?
Insofar, my workaround is as follows:
B4X:
If StrAt(a,StrLength(a)-2)=Chr(13) Then a=SubString(a,0,StrLength(a)-2)
This trims a string read from some.txt each time it is FileOpened. As a result, we always have only one extra crlf at the end of some.txt (no matter how many times the save button was fired).
Any other solutions (didn't find any on the forum yet)?
You are correct. FileWrite writes a string and adds end of line characters.
Your solution is a good solution. You can also use BinaryFile library and convert the string to bytes and write it with WriteBytes.
I think that the high-level answer is that FileWrite is a better match to FileRead because the latter just gives you the line content without new-line. So writing the same string with FileWrite puts back the new-line.
FileReadTo End does not match FileWrite so closely as you have discovered.
WriteBytes's an interesting option. I believe it should work faster (shouldn't it?), and indeed, it doesn't add crlf:
B4X:
Sub Globals
Dim buffer(0) As Byte
a=""
End Sub
Sub cmdOpen_Click
ErrorLabel(errFO)
FileOpen(c1,"some.txt",cRead)
a = FileReadToEnd(c1)
FileClose(c1)
Return
errFO:
Msgbox("Can't open it, dude!")
End Sub
Sub cmdSaveByte_Click
ErrorLabel(errFSB)
FileOpen(c1,"some.txt",cRandom)
bin.New1(c1,False)
buffer()=bin.StringToBytes(a)
bin.WriteBytes(buffer())
FileClose(c1)
Return
errFSB:
Msgbox("Can't save it, dude!")
End Sub
And finally, is it okay to combine a text method (FileReadToEnd) for opening file with a binary method (WriteBytes) for saving it? In particular, wouldn't the dynamic array of bytes (buffer()) create a memory overhead when saving a significant amount of text (as it doubles the same data, I suspect)?
I don't think that it will be faster. It will probably run at the same speed.
It does create an extra array. However if the text file is not huge then it will not really matter.
As long as you only write the string converted to bytes then you can safely read it with FileReadToEnd.