Home AMX User Forum AMX General Discussion

file_read_line

I tried to use file_read_line today, and noticed a problem. I haven't used it for a long time, likely prior to the NX series coming out, so I wonder if it changed. Its supposed to keep reading a line from a file until hitting EOF. However, when I used it on a file with a few blank lines (crlf only) scattered throughout, as soon as it hits one, it returns nothing, and stops. I had thought that it kept moving the file pointer to the byte after the last line until EOF is found, but it stopped long before EOF. The third line in my file is a blank line with just crlf, and that seems to stop it and reset the pointer. This is pretty much a useless function if its going to do that. It also removes the newline from the returned string which is a little odd, but I can deal with that. Anyone had any experience with this builtin function?

An interesting aside is that sending the strings from the file to a touch panel, the crlf also shows up on the touch panel. There is no need to send '|' to create a new line, as crlf does the same thing, at least on my iPad. However, I actually need to send the pipe character '|' to the touch panel, but I can't since it is interpreted as a newline. Apparently there is no way to send the pipe character to a touch panel due the interpretation of it as a newline, which isn't even needed since crlf works just as well. I can add a pipe character to a button though and it shows up as a pipe character. Anyone know how to send a pipe character to a touch panel?
Paul

Comments

  • ericmedleyericmedley Posts: 4,177
    If I'm reading your post correctly the answer is, as I understand it, File_Read_Line has always stopped at a the end of a line. (or to the EOF if on the last line)
    It's just Read_FIle that does as you describe.

    Here's the blurb from the help file.
    Remarks:

    This function reads from the current location of the file pointer up to the next carriage return or to the end-of-file (EOF), whichever comes first. A complete line will not be read if the buffer length is exceeded before a carriage return (or EOF) is encountered. The bytes are read from the file identified by HFile and are stored in Buffer. The <CR> or <CR><LF> pair will not be stored in Buffer. If a complete line is read, the file pointer is advanced to the next character in the file after the <CR> or <CR><LF> pair or to the EOF if the last line was read.

    I do have code running right now on NXs utilizing the command and it hasn't bonked on me.
    E
  • MLaletasMLaletas Posts: 226
    I use read_line all the time. I have it stuck in a while with the return value from the read_line function as the parameter. I cant recall ever an issue unless it was self-inflicted.
  • a_riot42a_riot42 Posts: 1,624
    read_file is what I am using now, but file_read_line is a function in almost every language, and normally reads through the entire file before resetting the file seek pointer once EOF is found.

    As I understood the help file, its supposed to read the file until encountering a CR, and then put the line in the buffer, moving the file seek pointer to the next character in the file in preparation for the next call of file_read_line. But it appears that if you have a newline on its own, its incorrectly interpreted as EOF. So doing a file_read_line on a file with a few blank lines scattered throughout never makes it through the whole file. As soon as a blank line is encountered, further calls to file_read_line returns 0 or no bytes read. So file_read_line can't be used on a file with a blank line in it? That's a fairly useless function, since most text files have a blank line or two. Some even start with one, in which case this function doesn't work at all.

    In order to read past a blank line the file must be reopened, file pointer moved to where it left off, and continue. So unless your file has no blank lines, this function is basically useless. I seem to recall using it before and not seeing this behavior so I thought perhaps it changed over time. Currently running FW 1.5.78.

    My file contains this:
    11:32:07 > Discovery profile: Default discovery profile
    11:32:07 > Discovery class: data-link (data-link layer)
    11:32:07 > Discovery on: 192.168.1.0/24
    11:32:07 > Discovery round starting.

    11:32:08 > Discovery progress 25%
    button_event[vdvTest, 1]
    {
        push:
    
            local_var sString[512]
            stack_var slong slFH, slBytesRead
    
            slFH  = file_open('test.txt', file_read_only)
            slBytesRead = file_read_line(slFH, sString, 512)
            while(slBytesRead)
                slBytesRead = file_read_line(slFH, sString, 512)
            db("'slBytesRead: ', itoa(slBytesRead)")
            dbug("'Line read: ', sString")
            file_close(slFH)    }
    }
    


    This is the ouput:
    (13:09:59):: File open result: 2
    (13:09:59):: slBytesRead: 55
    (13:09:59):: Line read: 11:32:07 > Discovery profile: Default discovery profile
    (13:09:59):: slBytesRead: 57
    (13:09:59):: Line read: 11:32:07 > Discovery class: data-link (data-link layer)
    (13:09:59):: slBytesRead: 45
    (13:09:59):: Line read: 11:32:07 > Discovery on: 192.168.1.0/24
    (13:09:59):: slBytesRead: 36
    (13:09:59):: Line read: 11:32:07 > Discovery round starting.
    (13:09:59):: slBytesRead: 0
    (13:09:59):: Line read:
    (13:09:59):: Line read:

    The line after the CRLF on its own, "11:32:08 > Discovery progress 25%" is never read.


    If I insert a newline as the first line, I don't get anything in the buffer.
    Paul
  • MLaletasMLaletas Posts: 226
    This is the way I would have done it:
    button_event[vdvTest, 1]
    {    
        push:    
        {        
            local_var sString[512]        
            stack_var slong slFH, slBytesRead
            slFH = file_open('test.txt', file_read_only)
            IF( slFH > 0 )
            {
                slBytesRead = 1 //Allow it to go into the while at least once        
               while( slBytesRead > 0 )        
               {            
                   slBytesRead = file_read_line(slFH, sString, 512)
                   db("'slBytesRead: ', itoa(slBytesRead)")
                   dbug("'Line read: ', sString")
              }
              file_close(slFH)
            }
        }
    }
    
  • a_riot42a_riot42 Posts: 1,624
    That's out of the help file example, and the only difference is seeding the result to get into the while loop. Does your code work after a line with CRLF appears on its own? In other words, two CRLFs in a row?
    Paul
  • MLaletasMLaletas Posts: 226
    I'll confirm tomorrow morning, I was thinking I should have probably tested that before i posted.
  • MLaletasMLaletas Posts: 226
    Paul, your absolutely right man, two in a row makes it think its EOF
  • MLaletasMLaletas Posts: 226
    Are you in control of the text file that your reading from? If so what I do when im reading lets say a config file any comments i put or for easier readability i put // and when I am reading in the data anything with a // I just ignore.
  • KielLKielL Posts: 29
    This seemed like very strange behavior, so I checked the definition in NetLinx help. FILE_READ_LINE returns >= 0 on success, and a few negative values for failure (-9 for when EOF is reached). So your WHILE loop should be:
    while(slBytesRead >= 0)
    {
        // stuff
    }
    

    I don't have an NX processor to test with, but with my NI, blank lines with only a CRLF return 0 and I can read several in succession without FILE_READ_LINE saying I've hit EOF. I don't think I've ever noticed that it doesn't count CRLF's in the result. I must have lucked out and never had to loop over any blank lines.
  • MLaletasMLaletas Posts: 226
    Good catch KeIL!

    Just tested it out on my offices NX, i have three CR_LF's in a row and no problem.
    Line    295 2017-05-03 (15:35:04)::  CONFIG READ: Source 4: ControlIPPort-
    Line    296 2017-05-03 (15:35:04)::  CONFIG READ: Source 4: ControlLogin-
    Line    297 2017-05-03 (15:35:04)::  CONFIG READ: 
    Line    298 2017-05-03 (15:35:04)::  CONFIG READ: 
    Line    299 2017-05-03 (15:35:04)::  CONFIG READ: 
    Line    300 2017-05-03 (15:35:04)::  CONFIG READ: Source 4: ControlPassword-
    Line    301 2017-05-03 (15:35:04)::  CONFIG READ: //Power Off
    Line    302 2017-05-03 (15:35:04)::  CONFIG READ: Source 5: SourceChannel-99
    
  • a_riot42a_riot42 Posts: 1,624
    KielL wrote: »
    This seemed like very strange behavior, so I checked the definition in NetLinx help. FILE_READ_LINE returns >= 0 on success, and a few negative values for failure (-9 for when EOF is reached). So your WHILE loop should be:
    while(slBytesRead >= 0)
    {
    // stuff
    }
    

    I don't have an NX processor to test with, but with my NI, blank lines with only a CRLF return 0 and I can read several in succession without FILE_READ_LINE saying I've hit EOF. I don't think I've ever noticed that it doesn't count CRLF's in the result. I must have lucked out and never had to loop over any blank lines.

    That must be it. I guess what it does is it removes the crlf prior to returning the bytes read which is a little counterintuitive. Therefore, if that is the only thing on that line, it returns 0 as the bytes read, even though it obviously read them. I had thought that it would have returned a positive integer since it has to read the crlf, but I guess since its removed, its not counted as part of the bytes read. I'm still confused why it removes the crlf, since in my case I need them, and now have to add it back. Nonetheless, at least using file_read_line instead of file_read takes care of advancing the read pointer automatically which is what I wanted. I am now slurping the whole file using file_read, but that can be slow with big files so this is a better alternative for what I am doing.
    Thanks for taking a second look!
    Paul

Sign In or Register to comment.