By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,569 Members | 1,350 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,569 IT Pros & Developers. It's quick & easy.

Carriage Return is messing up my program

P: 2
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:

Expand|Select|Wrap|Line Numbers
  1. sub Load {
  2.     my $file = &Prompt("File Name?");
  3.     open(INFO, $file);    # Open the file
  4.     my @lines = <INFO>;    # Read it into an array
  5.     close(INFO);
  6.  
  7.     my $index = 0;
  8.  
  9.     my @buffer1;
  10.  
  11.     while (@lines) {
  12.         $nextline = pop @lines;
  13.  
  14.         while (length($nextline) != 0) {
  15.             $buffer1[$index] = ord chop($nextline);
  16.             $index++;
  17.         }
  18.     }
  19.  
  20.     # It was loaded backward, so let's reverse it
  21.  
  22.     $bufferlength = $index;
  23.  
  24.     my @buffer2;
  25.  
  26.     for ($index=0; $index < $bufferlength; $index++) {
  27.         $buffer2[$index]=pop(@buffer1);
  28.     }
  29.  
  30.     @buffer2; #return the array
  31. }
  32.  
  33.  
  34.  
  35. #####write to file#####
  36. sub WriteToFile {
  37.     my $filename=&Prompt("new file name?");
  38.  
  39.     if ($filename eq "") {
  40.         print "No FILE WRITTEN!";
  41.  
  42.     } else {
  43.         open(INFO2, ">$filename");        # Open the file
  44.         for ($index=0; $index < $bufferlength; $index++) {
  45.             {
  46.                 use integer;
  47.                 $temp = $buffer[$index]*1;
  48.  
  49.                 print INFO2 chr $temp; #####another problem is here
  50.             }
  51.         }
  52.         close(INFO2);
  53.     }
  54. }
  55.  
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?
Jun 3 '07 #1
Share this Question
Share on Google+
5 Replies


miller
Expert 100+
P: 1,089
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
Jun 4 '07 #2

AdrianH
Expert 100+
P: 1,251
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:
Expand|Select|Wrap|Line Numbers
  1. #####Load the file#####
  2. use strict;
  3. use warnings;
  4.  
  5. sub Load
  6. {
  7.   my $file=&Prompt("File Name?");
  8.   open(INFO, $file);        # Open the file
  9.   my @lines = <INFO>;        # Read it into an array
  10.   close(INFO);
  11.  
  12.   my $index=0;
  13.  
  14.   my @buffer1;
  15.  
  16.   while (@lines)
  17.   {
  18.  
  19.     $nextline=pop(@lines);
  20.  
  21.     while (length($nextline) != 0)
  22.     {
  23.       $buffer1[$index]=ord chop($nextline); 
  24.  
  25.       $index++;
  26.     }
  27.   }
  28.  
  29.   #It was loaded backward, so let's reverse it
  30.  
  31.   $bufferlength=$index;
  32.  
  33.   my @buffer2;
  34.  
  35.   for ($index=0; $index < $bufferlength; $index++)
  36.   {
  37.     $buffer2[$index]=pop(@buffer1);
  38.   }
  39.  
  40.   @buffer2; #return the array
  41. }
  42.  
  43.  
  44.  
  45. #####write to file#####
  46. sub WriteToFile
  47. {
  48.   my $filename=&Prompt("new file name?");
  49.   if ($filename eq "")
  50.   {
  51.     print "No FILE WRITTEN!";
  52.   }
  53.   else
  54.   {
  55.     open(INFO2, ">$filename");        # Open the file
  56.     for ($index=0; $index < $bufferlength; $index++)
  57.     {
  58.       {
  59.         use integer;
  60.         $temp=$buffer[$index]*1;
  61.  
  62.         print INFO2 chr $temp; #####another problem is here
  63.  
  64.       }
  65.     }
  66.     close(INFO2);
  67.   }
  68. }
  69.  
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
Jun 4 '07 #3

P: 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
Thank you. It works great now.
Jun 4 '07 #4

P: 5
#

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

Thank you. It works great now.
Jun 4 '07 #5

miller
Expert 100+
P: 1,089
Thank you. It works great now.
Glad I could help.

- Miller
Jun 4 '07 #6

Post your reply

Sign in to post your reply or Sign up for a free account.