Writing Text File to Windows does not write entire file but works on Mac

I’ve got a small Method intended write out to a CSV file the info needed for Address labels. It works as expected on the Mac, but I only get the header line and the first line I’m getting from any array in windows.

Here’s the code:

var x as integer = 0
var ReturnStr as string
var recordstr as string
var f as FolderItem
f = FolderItem.ShowSaveFileDialog("Plain/text","Contacts-label.csv")
If f <> Nil Then
  Var t As TextOutputStream = TextOutputStream.Create(f)
  Try
    
    recordstr="FirstName,MiddleName,LastName,Address,City,State,Zipcode"
    t.Writeline(recordstr)
    
    do until ContactRecords(x,15)="Inactive"
      recordstr=App.ContactRecords(x,0)+","+App.ContactRecords(x,1)+","+App.ContactRecords(x,2)+","+App.ContactRecords(x,4)+","+App.ContactRecords(x,5)+","+App.ContactRecords(x,6)+","+App.ContactRecords(x,7)
      t.Writeline(recordstr)
      x=x+1
    loop
    t.close
    ReturnStr="Export Complete"
    Return ReturnStr
  Catch e As IOException
    // handle error
    Returnstr="File Write Error"
    Return ReturnStr
  End Try
else
  ReturnStr="Export Cancelled"
  return ReturnStr
End If

Have you tried tracing the code?

1 Like

Do the records come from a database?
A SQL query does not always return values in the same order.

have you checked whether more than one line is attempted?
(ie how many elements does the array actually have?)

Are you opening the CSV file in Excel? Excel locks the file against being written.
Do any of the fields contain a chr(0) or chr(26) which might make the CSV file truncate?

Your first step would be to try

   t.Writeline(recordstr)
msgbox recordstr  //or system debug logging

just to check the anticipated row count

Not exactly sure what you mean by “Tracing the code”

Setting a breakpoint in your code, then stepping through it and checking the variable values to see exactly what it’s doing and why.

A couple of things:

  1. How are you filling App.ContactRecords? Is it for sure filled on Windows?
  2. Your do loop says “do until ContactRecords=Inactive”. Does it need “App.” in front?
  3. Not necessarily related to this, but in general what will happen with your do loop if ContactRecords(x,15) never = “Inactive”?
1 Like

The record is not from a database, it’s from a CSV file that has been pulled into an array. I can verify that it’s in the array properly.

I know how many lines are in the array and I can see each record with other parts of my application. I’ve tried using notepad and I only see the first line from the array.

I have not checked for chr(0) or chr(26), but I will do that.

The fact that this is working on the Mac and I suspect Linux (which I haven’t tried yet) makes me think there is something going on with the end of line info, but I don’t know.

Since I’m not doing anything strange here, it seems to me that XoJo should handle this when it creates the Windows build.

Have you tried

t.Flush

before you close the stream?

1 Like

Are you aware of the encoding problems for text files? Not sure if this is related to that but Xojo made a mess with silent chnages on the TextOutputStream, maybe if you define the encoding of the TextOutputStream for your target OS:

Var t As TextOutputStream = TextOutputStream.Create(f)
output.Encoding = Encodings.WindowsANSI

All file.Close() implies in an auto-flush.

It appears there is an issue in your Contact Function… I cleaned-up the code above and moved the individual write lines to an array that is only written to file once and immediately closed. That should reduce CPU and system bog when writing 1000’s of records.

var x as integer = 0
var f as FolderItem = FolderItem.ShowSaveFileDialog("Plain/text","Contacts-label.csv")
Var WriteArray() as String

If isNull(f) then return "Export Cancelled"

Try
  Var t As TextOutputStream = TextOutputStream.Create(f)
  Var recordstr as String ="FirstName,MiddleName,LastName,Address,City,State,Zipcode"
  
  While App.ContactRecords(x,15)="Inactive"
    recordstr=App.ContactRecords(x,0)+","+App.ContactRecords(x,1)+","+App.ContactRecords(x,2)+","+App.ContactRecords(x,4)+","+App.ContactRecords(x,5)+","+App.ContactRecords(x,6)+","+App.ContactRecords(x,7)
    WriteArray.Add(recordstr)
    x=x+1
  Wend
  
  t.Write( String.FromArray(WriteArray, endofline) )
  t.close
  
  Return "Export Complete"
  
Catch e As IOException
  // handle error
  Return "File Write Error"
End Try

**I created test functions to satisfy the missing ContactRecords function, and the above seemed to work on Windows with no issues. Check your ContactRecords function and step-thru it as Christian advises above.

1 Like

Those codes are antagonistic.

WendLoop

@Rick_A

**In my experience speed is important when coding applications and a factor of ‘best practices’. While/Wend tends to take slightly less time to process a loop than Do-Loop. - not much different, but every bit counts. Depending on the contents of the Do-Loop & While/Wend, these will actually flip-flop on occasion in terms of speed (notably with embedded For/next loops)

#Pragma DisableBackgroundTasks True
#Pragma DisableBoundsChecking True
#Pragma StackOverflowChecking False


Var x as integer = 0
Var k as Double = System.Microseconds

While x <> 1000000
  x = x+1
wend

Var  L as Double = system.Microseconds
x = 0


Var i as Double = System.Microseconds

Do until x = 1000000
  x = x+1
loop

Var j as Double = System.Microseconds


MessageBox "Do/Loop took - " + str(j - i) + " microseconds. While/Wend took - " + str(l-k) + " microseconds. Both processed 1,000,000 loops"

Should that be <> “Inactive”?

2 Likes

Indeed :slight_smile: see my speed code example.

Eric,

t.Flush did the trick. Thanks!

Actually, no. This tells my code to not write out anymore lines once it finds the first “Inactive” in that field in the array. I won’t go into details on that since the rest of the code is working fine, and the fact that this only had an issue with Windows during the writeline part of the code. If this had been an issue, my code would not be working.

t.flush was the fix. :slight_smile:

I’ll repeat my earlier question, what happens when you have no inactive records? Hint: it won’t be good.

That is a great point Bill…sorry, I overlooked that as I’ve been doing multiple things today and not all on the computer. I’ll tweak my code to deal with that possibility.

1 Like

If flush() did the trick, close() seems defective and needs Xojo intervention and fixing. It should maintain the consistent behavior cross-platforms.

https://www.gnu.org/software/libc/manual/html_node/Closing-Streams.html

4 Likes