Carriage Return is messing up my program

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Detlev808
    New Member
    • Jun 2007
    • 2

    Carriage Return is messing up my program

    Hello,

    I am attempting to write an awesome perl script. Before it can do anything useful, it must first be able to read in a file, and write out a file (Note: I am NOT talking about text files). Here are the two subroutines I wrote to try to do this:

    [CODE=perl]
    sub Load {
    my $file = &Prompt("Fil e Name?");
    open(INFO, $file); # Open the file
    my @lines = <INFO>; # Read it into an array
    close(INFO);

    my $index = 0;

    my @buffer1;

    while (@lines) {
    $nextline = pop @lines;

    while (length($nextli ne) != 0) {
    $buffer1[$index] = ord chop($nextline) ;
    $index++;
    }
    }

    # It was loaded backward, so let's reverse it

    $bufferlength = $index;

    my @buffer2;

    for ($index=0; $index < $bufferlength; $index++) {
    $buffer2[$index]=pop(@buffer1);
    }

    @buffer2; #return the array
    }



    #####write to file#####
    sub WriteToFile {
    my $filename=&Prom pt("new file name?");

    if ($filename eq "") {
    print "No FILE WRITTEN!";

    } else {
    open(INFO2, ">$filename "); # Open the file
    for ($index=0; $index < $bufferlength; $index++) {
    {
    use integer;
    $temp = $buffer[$index]*1;

    print INFO2 chr $temp; #####another problem is here
    }
    }
    close(INFO2);
    }
    }
    [/CODE]

    As you can see, the load subroutine reads the file and creates an array where each element corresponds to a byte in the file converted to integer form (they must be integers so I can manipulate them). The WriteToFile subroutine converts each integer in the array to a character, and then writes it to a file.

    This code seems to work perfectly 99% of the time. That 1% where it doesn't work irritates the heck out of me. After a week of tracking the bug I believe I found the problem:

    When the file contains a byte that is 10 (in decimal, or NL in ascii), the WriteToFile function ends up writing 13 10 (or CR NL)--A carriage return is added. Also, when the load function reads a file that contains 13 10, only 10 is read--the carriage return is ignored (You should understand why this took me so long to find. I had to use another language to see what is happening).

    Is there a way to stop this from happening? Is there a better way to load/save non-ascii files?
    Last edited by miller; Jun 3 '07, 11:59 PM. Reason: Code Tag and ReFormatting
  • miller
    Recognized Expert Top Contributor
    • Oct 2006
    • 1086

    #2
    Greetings Detlev,

    Putting aside all best code practices advice and criticism concerning your method of implementation, what you need is binmode.

    perldoc binmode

    This is what lets you treat an input or output stream as binary versus text. Text gets special handling of the \n character for different operating systems. Just read the full documentation for the details.

    - Miller

    Comment

    • AdrianH
      Recognized Expert Top Contributor
      • Feb 2007
      • 1251

      #3
      Originally posted by Detlev808
      Hello,

      I am attempting to write an awesome perl script. Before it can do anything useful, it must first be able to read in a file, and write out a file (Note: I am NOT talking about text files). Here are the two subroutines I wrote to try to do this:
      [code=perl]
      #####Load the file#####
      use strict;
      use warnings;

      sub Load
      {
      my $file=&Prompt(" File Name?");
      open(INFO, $file); # Open the file
      my @lines = <INFO>; # Read it into an array
      close(INFO);

      my $index=0;

      my @buffer1;

      while (@lines)
      {

      $nextline=pop(@ lines);

      while (length($nextli ne) != 0)
      {
      $buffer1[$index]=ord chop($nextline) ;

      $index++;
      }
      }

      #It was loaded backward, so let's reverse it

      $bufferlength=$ index;

      my @buffer2;

      for ($index=0; $index < $bufferlength; $index++)
      {
      $buffer2[$index]=pop(@buffer1);
      }

      @buffer2; #return the array
      }



      #####write to file#####
      sub WriteToFile
      {
      my $filename=&Prom pt("new file name?");
      if ($filename eq "")
      {
      print "No FILE WRITTEN!";
      }
      else
      {
      open(INFO2, ">$filename "); # Open the file
      for ($index=0; $index < $bufferlength; $index++)
      {
      {
      use integer;
      $temp=$buffer[$index]*1;

      print INFO2 chr $temp; #####another problem is here

      }
      }
      close(INFO2);
      }
      }
      [/code]

      Originally posted by Detlev808
      As you can see, the load subroutine reads the file and creates an array where each element corresponds to a byte in the file converted to integer form (they must be integers so I can manipulate them). The WriteToFile subroutine converts each integer in the array to a character, and then writes it to a file.

      This code seems to work perfectly 99% of the time. That 1% where it doesn't work irritates the heck out of me. After a week of tracking the bug I believe I found the problem:

      When the file contains a byte that is 10 (in decimal, or NL in ascii), the WriteToFile function ends up writing 13 10 (or CR NL)--A carriage return is added. Also, when the load function reads a file that contains 13 10, only 10 is read--the carriage return is ignored (You should understand why this took me so long to find. I had to use another language to see what is happening).

      Is there a way to stop this from happening? Is there a better way to load/save non-ascii files?
      Well, if you are relying on CR and/or LF as your record separator, looks to me like you are using a text file.

      Try using read to read it all in, then use split with a regex of /(\r\n|\n\r|\n|\ r)/ on the read in string. From there I think your read routine will work.

      As for writing a scalar, I’m not sure.

      BTW, please use [code=perl]...your code here...[/code] tags and INDENT to improve readability.


      Adrian

      Comment

      • Detlev808
        New Member
        • Jun 2007
        • 2

        #4
        Originally posted by miller
        Greetings Detlev,

        Putting aside all best code practices advice and criticism concerning your method of implementation, what you need is binmode.

        perldoc binmode

        This is what lets you treat an input or output stream as binary versus text. Text gets special handling of the \n character for different operating systems. Just read the full documentation for the details.

        - Miller
        Thank you. It works great now.

        Comment

        • jabirahmed
          New Member
          • Jun 2007
          • 5

          #5
          #

          #
          $nextline=pop(@ lines);
          try a chomp($nextline );

          Originally posted by Detlev808
          Thank you. It works great now.

          Comment

          • miller
            Recognized Expert Top Contributor
            • Oct 2006
            • 1086

            #6
            Originally posted by Detlev808
            Thank you. It works great now.
            Glad I could help.

            - Miller

            Comment

            Working...