Loading Mac/Windows Text File

I have a text file that I created on Mac [Word : Description CR ]

I store it in the Apps folder and read it when a particular window opens.
On the Mac it works fine but on Windows it doesn’t.
On the Mac when I view it in the finder it shows one Word/Description per line
On Windows it shows it as one continuous block of text.
What do I have to do to make the file the same on both platforms?

macOS uses LF (0x0A) as the end of line
Windows uses CRLF (0x0A0D)

so you may need to do a REPLACELINENDINGS for Windows

Thanks Dave,
Is there an encoding that should be set and is it different on Mac and Windows?

I tried
s1 = fileToUse.OpenAsBinaryFile(True)
p = s1.Length
temp1 = s1.read§
s1.close
Temp1 = DefineEncoding(temp1, Encodings.UTF18)

if TargetMacOS then
temp1 = ReplaceLineEndings(temp1, endofline.OSX)
else
temp1 = ReplaceLineEndings(temp1, endofline.Windows)
end if

But still get an error

Don’t worry about specifying the endofline type. just use

temp1 = ReplaceLineEndings(temp1, endofline)

As far as encoding goes… it depends on what created the file. You could open it in a program like BBEdit and it’ll probably tell you what the encoding is if it’s something specific.

Does your file have a BOM?

I created it in Mac Textedit and what is a BOM?

BOM = Byte order mark. See https://en.wikipedia.org/wiki/Byte_order_mark .

A couple of invisible-to-the-eye bytes at the start of a text file which indicates that it is a unicode file, and what type,
causing (usually older) applications which expect a TXT file to be a ‘simple character array’ to have a fit.

Ok, but still stumped.

Here is the test file

http://appdata.sallyfitzgibbons.com/AppData/Wizard/Test_20W_Dictionary.txt
No problem reading it on the Mac but can’t get the Windows App to split it into the same lines??

Greg answered this already here: https://forum.xojo.com/conversation/post/400560

If this does not work, please post the Code you use.

Its text.
Why are you opening it as a binary file at all?

s1 = fileToUse.OpenAsBinaryFile(True)
Dim f As FolderItem
Dim textInput As TextInputStream
Dim i As Integer
f = fileToUse
If f <> Nil And f.Exists Then
  textInput = TextInputStream.Open(f)
 // textInput.Encoding = Encodings.MacRoman 
  While Not textInput.EOF
    rowFromFile = textInput.ReadLine
    
    ListBox1.AddRow rowFromFile

  Wend
  textInput.Close
End If

Martin,

do you have a solid reason to open the text file with a BinaryStream ?
If so, maybe we can give you a solution to do the “same” with TextInputStream.

[quote=400617:@Emile Schwarz]Martin,

do you have a solid reason to open the text file with a BinaryStream ?
If so, maybe we can give you a solution to do the “same” with TextInputStream.[/quote]

Isn’t that what @Jeff Tullin wrote??? :confused:

No, complementary. In my mind, there can be two reasons why to use a BinaryStream for reading a Text file:

a. Why not (so, maybe an error); or… it works,

b. a specific reason, for example using the Position property (of BinaryStream).

In case of b, it is possible to do otherwise.

Setting an encoding is possible with BinaryStream:

TextArea1.Text = ReadStream.Read(1000, Encodings.UTF8)

Here is the full method which reads the file and adds to a Dictionary

// This method assumes file format of key space : space defintion CR
// with the first line of the file being the count of items in the file
Dim l,m,n,o,p As Integer
Dim s1 As BinaryStream
Dim a,temp1,myKey,myValue As String
Dim whichBin,holdBin as Integer
Dim theCount As Integer

if fileToUse.Exists then
ourDict = New Dictionary
DictionaryChanged = false
NeedsSorted = false //assumes input is sorted
s1 = fileToUse.OpenAsBinaryFile(True)
p = s1.Length
temp1 = s1.read§
s1.close
Temp1 = DefineEncoding(temp1, Encodings.MacRoman)
temp1 = ReplaceLineEndings(temp1, endofline)
m = 1
// get number of items in dictionary file
l = InStrb(m,temp1,endofline)
theCount =val(Midb(temp1,m,(l-1)))

Redim wordList(theCount)
theCount = 0 // set back to 0
m=l+1
// load the dictionary
do
l = InStrB(m,temp1,":")
if l = 0 then
exit
end if
myKey = MidB(temp1,m,(l-1-m)) // strip trailing blank and :
myKey = Uppercase(myKey) // store as uppercase
n = InStrB(l,temp1,endofline)
if n = 0 then
n = p // last item to process
end if
myValue = MidB(temp1,l+2,n-2-l) // strip leading blank
m = n + 1
if ourDict.HasKey(myKey) = False then // use only first one, if duplicates
ourDict.Value(myKey) = myValue // add to Dictionary
o = ourDict.Count - 1
//wordList.Append ourDict.Key(o)
wordList(theCount) = ourDict.Key(o)
theCount = theCount + 1
// update bins
whichBin = ascB(midB(myKey,1,1)) - 64 //index a=1
wordIndex(whichBin) = wordIndex(whichBin) + 1
end if
loop until thecount = wordlist.ubound’n = p
// finalize bins
for l = 0 to 25
holdBin = holdBin + wordIndex(l + 1)
wordIndex(l+1) = holdBin
next

else
raise new NilObjectException

end if
Exception
Raise new NilObjectException

Cant work out what the bins are for.
Assuming you need to count the instances, try this:

if you need to hold a count of several things, such as Things in Locations versus Things Total then one way would be to use two dictionaries … a Locations one and a Things one.

[code]Dim f As FolderItem
Dim textInput As TextInputStream
Dim i As Integer
ourDict = New Dictionary

f = fileToUse
If f <> Nil And f.Exists Then
textInput = TextInputStream.Open(f)

While Not textInput.EOF

rowFromFile = textInput.ReadLine
rowFromFile = trim(replace(rowFromFile,":",""))

if ourdict.haskey(rowfromfile) then
ourdict.value(rowfromfile) = ourdict.value(rowfromfile) +1
else
ourdict.value(rowfromfile) =1
end if

Wend
textInput.Close
End If[/code]

[quote=400783:@Martin Fitzgibbons]temp1 = s1.read§
s1.close
Temp1 = DefineEncoding(temp1, Encodings.MacRoman)[/quote]

This is clear.

a. Why don’t you use TextInputStream ?

TextInputStream1.Encoding = Encodings.UTF8 temp1 = TextInputStream1.ReadAll(s1)
No need to read the file size, no need to set an encoding later.

b. Why don’t you use the Encoding in the BinaryStream1.Read line ?

Syntax: Readable.Read(Count as Integer[,Enc as TextEncoding]) As String

Do not answer on my Why lines (above), they are simple advices… :wink:

Hi Jeff,

Just getting back to this. I think all the old code was trying to achieve was to split a colon separated Word : Definition
into a dictionary and also append the Word into a wordlist array for a separate purpose, it was also trying not to add any duplicates but that isn’t an issue for me to have duplicates. So I need to pull apart each line and add 2 fields to the dictionary
key =word value = definition. The bin part of the code seemed to be keeping track of what letter each word started with??

===================

[quote=400791:@Jeff Tullin]Cant work out what the bins are for.
Assuming you need to count the instances, try this:

if you need to hold a count of several things, such as Things in Locations versus Things Total then one way would be to use two dictionaries … a Locations one and a Things one.

[code]Dim f As FolderItem
Dim textInput As TextInputStream
Dim i As Integer
ourDict = New Dictionary

f = fileToUse
If f <> Nil And f.Exists Then
textInput = TextInputStream.Open(f)

While Not textInput.EOF

rowFromFile = textInput.ReadLine
rowFromFile = trim(replace(rowFromFile,":",""))

if ourdict.haskey(rowfromfile) then
ourdict.value(rowfromfile) = ourdict.value(rowfromfile) +1
else
ourdict.value(rowfromfile) =1
end if

Wend
textInput.Close
End If[/code][/quote]

No ater than earlier today, I used a TextInputStream to

read the six first lines of a file and send them each in its own TextField,
read the rest of the text file and put it into a TextArea.

Absolutely no trouble.