|
| 1 | +=title Don't Open Files in the old way |
| 2 | +=timestamp 2013-03-21T08:45:17 |
| 3 | +=indexes open |
| 4 | +=status show |
| 5 | +=books beginner_book |
| 6 | +=author szabgab |
| 7 | +=index 1 |
| 8 | +=archive 1 |
| 9 | +=feed 1 |
| 10 | +=comments 1 |
| 11 | +=social 1 |
| 12 | + |
| 13 | +=abstract start |
| 14 | + |
| 15 | +Earlier in the <a href="/perl-tutorial">Perl Tutorial</a> |
| 16 | +we saw how to open a file for reading or writing. |
| 17 | +Unfortunately, when you search the web, or when you look at code |
| 18 | +in corporations you will see some slightly different syntax. |
| 19 | + |
| 20 | +Let's see what is that, what is the problem with that and why to avoid? |
| 21 | + |
| 22 | +=abstract end |
| 23 | + |
| 24 | +<h2>So what shall I do?</h2> |
| 25 | + |
| 26 | +Before explaining what you should not do, let me link you to the articles explain what you should do: |
| 27 | + |
| 28 | +Read <a href="/open-and-read-from-files">how to open file for reading in a modern way</a> |
| 29 | +or the one about <a href="/writing-to-files-with-perl">writing to file in Perl</a>. |
| 30 | + |
| 31 | +Now let's get back to the old, and not-so-good-any-more practices. |
| 32 | + |
| 33 | +<h2>The old and not recommended way</h2> |
| 34 | + |
| 35 | +Until perl 5.6 came out - that's until 2000 - we used to write code |
| 36 | +like this to open a file for writing: |
| 37 | + |
| 38 | +<code lang="perl"> |
| 39 | +open OUT, ">$filename" or die ...; |
| 40 | +</code> |
| 41 | + |
| 42 | +and code like this for reading: |
| 43 | + |
| 44 | +<code lang="perl"> |
| 45 | +open IN, $filename or die ...; |
| 46 | +</code> |
| 47 | + |
| 48 | +The "or die" part was the same as we do today, not fully spelled out here. |
| 49 | + |
| 50 | +As you can see <hl>open</hl> got two parameters. The first is a set |
| 51 | +of (usually upper-case) letters. That's the thing that will get the |
| 52 | +filehandle. The second is the combined opening mode and the path to |
| 53 | +the file that needs to be opened. |
| 54 | + |
| 55 | +That is, in the first case you see the greater-than sign meaning we |
| 56 | +are opening the file for writing, but in the second example we used to |
| 57 | +omit the opening mode. That's because <hl>open()</hl> defaults to reading. |
| 58 | + |
| 59 | +There are two big differences: |
| 60 | + |
| 61 | +<h2>Filehandle glob</h2> |
| 62 | + |
| 63 | +The first is that we use the strange variable without the |
| 64 | +leading <hl>$</hl> to hold the filehandle. |
| 65 | +(This is actually a <b>bareword</b>, but one that does not trigger |
| 66 | +the <a href="/barewords-in-perl">Bareword not allowed while "strict subs" in use</a> |
| 67 | +error.) |
| 68 | + |
| 69 | +It works as it worked in the early days of Perl, but there are several problems with it: |
| 70 | + |
| 71 | +It is global to all the script you write so if anyone |
| 72 | +uses the same name (IN or OUT in our example) those |
| 73 | +will clash with yours. |
| 74 | + |
| 75 | +It is also harder to pass these variables to functions, |
| 76 | +than to do the same with regular scalar variables. |
| 77 | + |
| 78 | +<h2>2 parameter open</h2> |
| 79 | + |
| 80 | +The second difference is the fact that in these examples <hl>open</hl> got only two parameters. |
| 81 | + |
| 82 | +What if the variable <hl>$filename</hl>, that you are using to open |
| 83 | +a file for reading, contains >/etc/passwd ? |
| 84 | + |
| 85 | +Oups. |
| 86 | + |
| 87 | +The <hl>open IN, $filename</hl> will actually open that file for writing. |
| 88 | + |
| 89 | +You just deleted the password file of your Linux operating system. |
| 90 | + |
| 91 | +Not good. |
| 92 | + |
| 93 | +<h2>Need to close that filehandle</h2> |
| 94 | + |
| 95 | +Another advantage of using <b>lexically scoped scalar variables</b> |
| 96 | +as filehandles is that they will automatically be closed when |
| 97 | +they go out of scope. |
| 98 | + |
| 99 | +<h2>How to avoid these problems?</h2> |
| 100 | + |
| 101 | +It's better to avoid both of these practices and use the "new", |
| 102 | +(available since 2000 !) <a href="/open-and-read-from-files">3-parameter open |
| 103 | +with scalar lexical variable</a> for storing the filehandle. |
| 104 | + |
| 105 | +There are even policies in <a href="http://www.perlcritic.com/">Perl::Critic</a> |
| 106 | +that will help you analyze the code and locate every place where someone has used either |
| 107 | +of the above forms. |
| 108 | + |
| 109 | +<h2>Good and Bad for reading</h2> |
| 110 | + |
| 111 | +Bad: |
| 112 | + |
| 113 | +<code lang="perl"> |
| 114 | +open IN, $filename or die ...; |
| 115 | +</code> |
| 116 | + |
| 117 | +Good: |
| 118 | + |
| 119 | +<code lang="perl"> |
| 120 | +open my $in, '<', $filename or die ...; |
| 121 | +</code> |
| 122 | + |
| 123 | +<h2>Good and Bad for writing</h2> |
| 124 | + |
| 125 | +Bad: |
| 126 | + |
| 127 | +<code lang="perl"> |
| 128 | +open IN, ">$filename" or die ...; |
| 129 | +</code> |
| 130 | + |
| 131 | +Good: |
| 132 | + |
| 133 | +<code lang="perl"> |
| 134 | +open my $in, '>', $filename or die ...; |
| 135 | +</code> |
| 136 | + |
| 137 | + |
0 commit comments