467,905 Members | 1,837 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 467,905 developers. It's quick & easy.

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:

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
  • viewed: 2161
Share:
5 Replies
miller
Expert 1GB
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 1GB
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
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
#

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

Thank you. It works great now.
Jun 4 '07 #5
miller
Expert 1GB
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.

Similar topics

3 posts views Thread by Canes_Rock | last post: by
4 posts views Thread by Dr. Laurence Leff | last post: by
4 posts views Thread by Josh | last post: by
12 posts views Thread by Nimmy | last post: by
6 posts views Thread by Laura D | last post: by
5 posts views Thread by Dixie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.