A needed a way to read a line from a file up to a maximum certain line length. I did some searching (including find this here: Read a line with max length ?) but couldn't find anything helpful to do it as a single function to call, so I created some code for doing it and released it to CPAN.

Just wanted to post here in case anyone does some searching in the future looking for the same thing.

File::GetLineMaxLength

Rob

Replies are listed 'Best First'.
Re: Read a line up to a maximum length
by jdalbec (Deacon) on Dec 11, 2004 at 16:09 UTC
    The OP wants a C fgets() workalike. The main reason for this function in C is to avoid buffer overflows. Perl should dynamically expand the buffer as needed so technically this would seem to be unnecessary, although the OP's concern about DoS seems reasonable. It might be simpler to use an inside-out-object implementation something like this:
    { my %buffers, %handles; sub fgets { my $fh = shift; my $max = shift; my $needed = $max - length $buffers{$fh}; $buffers{$fh} .= do {local $/ = \$needed; <$fh>} if $needed > 0; open $handles{$fh}, '<', \$buffers{$fh} unless $handles{$fh}; my $result = substr(readline $handles{$fh}, 0, $max); substr($buffers{$fh}, 0, length $result) = ''; seek $handles{$fh}, 0, 0; return $result; } } # test code open my $fh, '<', $0; while(my $line = fgets $fh, 20) { print "[$line]"; }
    ... but with error handling, of course. Need I mention that you shouldn't mix this fgets() with any other filehandle operations?
Re: Read a line up to a maximum length
by Limbic~Region (Chancellor) on Dec 11, 2004 at 14:22 UTC
    robmueller,
    I think I understand, but I want to be sure. At first I thought you only wanted the first x bytes of a line for each line discarding the rest:
    while ( <FOO> ) { $_ = substr($_, 0, 1024); # other stuff }
    Then after reading your documentation, it looks like you want to avoid this because the newline may be so far away that you fill up all your memory. In fact, it appears that you want to continue reading the line and not start on the next one. Most of the time, people would just say to do:
    { local $/ = \1024; while ( <FOO> ) { # stuff } } # or sysread FOO, $_, 1024; # keeping track of offset
    But your module adds one "feature". If the value of $/ and the time new was called is found in the buffer, only the portion up to that is returned and the remainder is left in the buffer for susequent calls.

    So instead of getting consistent results I may get 1024 bytes or 1 byte depending on where things fell? Doesn't seem like a very useful module to me but I could be way out in left field here. The reason sysread passes the scalar to store the results as one of the parameters is so that it can return the actual number of bytes read (0 if eof and undef if error).

    Cheers - L~R

Re: Read a line up to a maximum length
by castaway (Parson) on Dec 11, 2004 at 13:00 UTC
    Is there any particular reason you didn't use read, sysread or any of the other suggestions posted in that thread? You didn't exactly participate in the discussion, or say why those solutions don't work for you.

    C.