2008-11-25 16 views
43

कृपया ध्यान दें - मैं खोलने के लिए/एक फ़ाइल को पढ़ने "सही" जिस तरह से, या जिस तरह से मैं खोल देना चाहिए/एक फ़ाइल हर बार पढ़ा की तलाश नहीं कर रहा हूँ।) * मेरी पर्ल कार्यक्रमों में कोड कीपर्ल में फ़ाइल खोलने और पढ़ने का सबसे अच्छा तरीका क्या है?

एक बहुत ही आम ब्लॉक एक फ़ाइल और पढ़ने खोलने या करने के लिए लिख रहा है: मैं बस किस तरह से ज्यादातर लोगों का उपयोग पता लगाने के लिए, और शायद एक ही समय में कुछ नए तरीकों को जानने दिलचस्पी यह। मैंने ऐसा करने के कई तरीके देखे हैं, और इस काम को करने पर मेरी शैली कुछ वर्षों से बदल गई है। मैं बस सोच रहा हूँ क्या सबसे अच्छा (अगर कोई है एक सबसे अच्छा तरीका है) विधि यह करने के लिए है?

मैं इस तरह एक फ़ाइल खोलने के लिए इस्तेमाल किया:

my $input_file = "/path/to/my/file"; 
open INPUT_FILE, "<$input_file" || die "Can't open $input_file: $!\n"; 

लेकिन मैं उस त्रुटि फँसाने के साथ समस्या है लगता है।

open (INPUT_FILE, "<$input_file") || die "Can't open $input_file: $!\n"; 

मुझे पता है तुम भी एक चर करने के लिए एक filehandle असाइन कर सकते हैं, तो बजाय का उपयोग कर "INPUT_FILE" की तरह मैं ऊपर किया था, मैं $ इस्तेमाल किया जा सकता था:

एक कोष्ठक जोड़ने में त्रुटि फँसाने ठीक करने के लिए लगता है input_filehandle - क्या वह तरीका बेहतर है?

एक फ़ाइल को पढ़ने के लिए, यदि यह छोटा है, वहाँ कुछ भी ग्लोबिंग, इस तरह के साथ गलत क्या है?

my @array = <INPUT_FILE>; 

या

my $file_contents = join("\n", <INPUT_FILE>); 

या आप हमेशा लूप के माध्यम से, इस तरह करना चाहिए:

my @array; 
while (<INPUT_FILE>) { 
    push(@array, $_); 
} 

मुझे पता है कि कई मायनों पर्ल में चीजों को पूरा करने के लिए कर रहे हैं, मैं बस सोच रहा हूँ यदि फ़ाइल में खोलने और पढ़ने के पसंदीदा/मानक तरीके हैं?

+0

[perlopentut] (http://perldoc.perl.org/perlopentut.html) आदमी पेज बहुत अच्छी तरह से इस मुद्दे से ज्यादातर को शामिल किया गया। – converter42

उत्तर

58

कोई सार्वभौमिक मानक हैं, लेकिन वहाँ कारणों में से एक या एक और पसंद करते हैं करने के लिए कर रहे हैं। मेरे पसंदीदा प्रकार यह है:

open(my $input_fh, "<", $input_file) || die "Can't open $input_file: $!"; 

कारण हैं:

  • आप तुरंत त्रुटियों की रिपोर्ट। (साथ "मर" बदलें "चेतावनी दी है" कि अगर तुम क्या चाहते हो।)
  • आपका filehandle अब संदर्भ-गिना जाता है, तो एक बार आप इसे उपयोग नहीं कर रहे यह स्वचालित रूप से बंद कर दिया जाएगा। यदि आप वैश्विक नाम INPUT_FILEHANDLE का उपयोग करते हैं, तो आपको फ़ाइल को मैन्युअल रूप से बंद करना होगा या प्रोग्राम समाप्त होने तक यह खुला रहेगा।
  • पढ़ने के मोड सूचक "<" $ input_file से अलग है, बढ़ रही है पठनीयता।

निम्नलिखित महान अगर फाइल छोटा है और आप जानते हैं कि आप सभी लाइनों हैं:

my @lines = <$input_fh>; 

तुम भी आप एक ही स्ट्रिंग के रूप में सभी लाइनों पर कार्रवाई करने की आवश्यकता है, यह कर सकते हैं:

my $text = join('', <$input_fh>); 

लंबी फ़ाइलों के लिए आप समय के साथ लाइनों पर फिर से चलना चाहते हैं, या पढ़ने का उपयोग करना चाहते हैं।

+0

या मामूली विविधता ... मेरा $ input_fh खोलें, '<', $ input_file या मरें "$ input_file नहीं खोल सकता: $!"; – draegtun

+2

मुझे अभी भी लगता है कि यह बॉयलरप्लेट है। बस 'फ़ाइल :: स्लर्प' या 'टाई :: फ़ाइल' का उपयोग करें। – Svante

+0

__Nice संपादित करें टोफ! – monksy

14

यदि आप पूरी फ़ाइल को एक स्ट्रिंग के रूप में चाहते हैं, तो इसके माध्यम से पुन: प्रयास करने की आवश्यकता नहीं है।

use strict; 
use warnings; 
use Carp; 
use English qw(-no_match_vars); 
my $data = q{}; 
{ 
    local $RS = undef; # This makes it just read the whole thing, 
    my $fh; 
    croak "Can't open $input_file: $!\n" if not open $fh, '<', $input_file; 
    $data = <$fh>; 
    croak 'Some Error During Close :/ ' if not close $fh; 
} 

ऊपर संतुष्ट perlcritic --brutal है, जो 'सर्वोत्तम प्रथाएं' :) के लिए परीक्षण करने के लिए एक अच्छा तरीका है। $input_file अभी भी यहां अपरिभाषित है, लेकिन शेष कोशेर है।

+0

स्थानीय $ आरएस = undef क्या करता है; कर? –

+2

'$ आरएस'' $/'जैसा ही है जो आपके लिए 'अंग्रेजी' सेट अप करता है। '$ /' वह चर है जो '<$fh>' के लिए 'पंक्ति सेपरेटर' मान ट्रैक करता है, जो 'get-line', या' $ fh-> getline() 'की धारणा का पर्याय बन गया है। अनिवार्य रूप से, इसमें आंतरिक पढ़ने वाले एल्गोरिदम का मान होता है जब यह डेटा के पूर्ण 'रेखा' को पढ़ता है, और इसे 'undef'' पर सेट करने का अर्थ है "कोई मार्कर नहीं है जो पूर्ण रेखा को इंगित करता है" ताकि यह पूरी तरह से पढ़ सके फ़ाइल "लाइन" –

2

यदि ये प्रोग्राम केवल आपकी उत्पादकता के लिए हैं, जो कुछ भी काम करता है! जैसा कि आपको लगता है कि आपको आवश्यकता है उतनी त्रुटि प्रबंधन में बनाएं।

एक पूरी फाइल में पठन अगर यह बड़े, सबसे अच्छा तरीका है लंबे समय तक काम करने के लिए नहीं किया जा सकता है ताकि आप लाइनों पर कार्रवाई करने के लिए कर सकते हैं आते ही उन्हें बजाय एक सरणी में उन्हें लोड है।

द प्रोगामैटिक प्रोग्रामर (हंट & थॉमस) में अध्यायों में से एक से मुझे मिली एक युक्ति यह है कि आप स्क्रिप्ट स्लाईसिंग और डाइसिंग पर जाने से पहले स्क्रिप्ट को आपके लिए फ़ाइल का बैकअप सहेजना चाहेंगे।

11

यदि आपकी फाइलें इतनी छोटी हैं कि पूरी चीज को स्मृति में पढ़ना संभव है, तो File::Slurp का उपयोग करें। यह एक बहुत ही सरल एपीआई के साथ पूर्ण फाइलें पढ़ता है और लिखता है, साथ ही यह सभी त्रुटि जांच करता है ताकि आपको यह नहीं करना पड़े।

+1

फ़ाइल :: स्लर्प अद्भुत है, लेकिन यह केंट फ्रेड्रिक के प्रत्यक्ष पढ़ने से बहुत धीमी है। (~ 4000 10-30k फाइलें 7s सीधी बनाम 56s प्रतिलिपि प्रतिलिपि) –

6

फ़ाइल खोलने और पढ़ने का कोई अच्छा तरीका नहीं है। पूछना गलत सवाल है। फाइल में क्या है? किसी भी समय आपको कितना डेटा चाहिए? क्या आपको एक ही समय में सभी डेटा चाहिए? डेटा के साथ आपको क्या करने की ज़रूरत है? फ़ाइल को खोलने और पढ़ने की आवश्यकता के बारे में सोचने से पहले आपको उनको समझने की आवश्यकता है।

क्या आप अब कुछ भी कर रहे हैं जो आपको समस्याएं पैदा कर रहा है? यदि नहीं, तो क्या आपको हल करने में बेहतर समस्याएं नहीं हैं? :)

अपने प्रश्न में से अधिकांश केवल वाक्य रचना है, और है कि सभी पर्ल प्रलेखन (विशेष रूप से (perlopentut)। तुम भी Learning Perl लेने के लिए, जो आप अपने सवाल में है समस्याओं के सबसे उत्तर देता पसंद कर सकते हैं में दिए है।

गुड लक, :)

+0

तो शायद मुझे यह नहीं पूछा जाना चाहिए कि फ़ाइल खोलने/पढ़ने का सबसे अच्छा तरीका क्या है, लेकिन अधिकांश लोग क्या करते हैं। मैंने सैकड़ों perl प्रोग्राम लिखे हैं जो फाइलें खोलते हैं, और सिर्फ यह सुनिश्चित करना चाहते हैं कि मैं इसके बारे में अच्छी तरह से जा रहा हूं। मुझे कोई समस्या नहीं है - मैं सिर्फ उत्सुक हूं कि अन्य लोग इसे कैसे करते हैं। धन्यवाद! – BrianH

+0

फिर, पहले पैराग्राफ को पढ़ें। सबसे अच्छा तरीका यह है कि आप क्या कर रहे हैं पर निर्भर करता है। –

+0

मैं पर्ल नहीं कह रहा हूं :: आलोचना कानून है, लेकिन "लर्निंग पर्ल" में फाइलें खोलने के कई तरीके पर्ल :: आलोचना पास नहीं करते हैं। असल में, जिस तरह से मैं फ़ाइलों को हर समय खोलने के लिए उपयोग करता था, वैसे ही मैंने इसे "लर्निंग पर्ल" में सीखा। मैं तर्क दूंगा कि अधिकांश स्थितियों पर सर्वोत्तम प्रथाओं को लागू किया जा सकता है जहां फ़ाइल को खोला जाना चाहिए, और आपको छोटे विवरणों को जानने की आवश्यकता नहीं है - अन्यथा मैं पूछूंगा, "बाइनरी फ़ाइल खोलने और गिनने का सबसे अच्छा तरीका क्या है बाइट्स "या ऐसा कुछ। 99% फाइलें जो मैं खोलता हूं वह सादे पाठ हैं, और मैं इसे एक सरणी में पढ़ना चाहता हूं। मुझे सबसे अच्छा अभ्यास जानने में दिलचस्पी है – BrianH

5

OO के लिए, मुझे पसंद है:

use FileHandle; 
... 
my $handle = FileHandle->new("< $file_to_read"); 
croak("Could not open '$file_to_read'") unless $handle; 
... 
my $line1 = <$handle>; 
my $line2 = $handle->getline; 
my @lines = $handle->getlines; 
$handle->close; 
+0

और फिर आप इसे <$handle> के साथ पढ़ते हैं? – BrianH

+0

हां, यह "पुनरावृत्ति ऑपरेटर" के साथ काम करेगा, लेकिन आप इसे $ हैंडल-> गेटलाइन या $ हैंडल-> गेटलाइन – Axeman

5

यह सच है कि वहाँ के रूप में वहाँ

हैं पर्ल में एक फ़ाइल को खोलने के रूप में कई बेहतरीन तरीके हैं कि है
$files_in_the_known_universe * $perl_programmers 

... लेकिन यह अभी भी देखने के लिए जो आम तौर पर यह जो रास्ता करता है दिलचस्प है। slurping (ही बार में पूरा फ़ाइल को पढ़ने) का मेरा पसंदीदा प्रकार है:

use strict; 
use warnings; 

use IO::File; 

my $file = shift @ARGV or die "what file?"; 

my $fh = IO::File->new($file, '<') or die "$file: $!"; 
my $data = do { local $/; <$fh> }; 
$fh->close(); 

# If you didn't just run out of memory, you have: 
printf "%d characters (possibly bytes)\n", length($data); 

और जब जा रहा पंक्ति-दर-पंक्ति: निश्चित रूप से

my $fh = IO::File->new($file, '<') or die "$file: $!"; 
while (my $line = <$fh>) { 
    print "Better than cat: $line"; 
} 
$fh->close(); 

चेतावनी पाठभेद: ये सिर्फ दृष्टिकोण मैं कर रहे हैं हर रोज काम के लिए मांसपेशी स्मृति करने के लिए प्रतिबद्ध ve, और वे मौलिक समस्या को हल करने की कोशिश कर रहे के लिए अनुपयुक्त हो सकती है।

4

मैं एक बार नियमित रूप से

open (FILEIN, "<", $inputfile) or die "..."; 
my @FileContents = <FILEIN>; 
close FILEIN; 

बॉयलरप्लेट का इस्तेमाल किया।आजकल, मैं बड़ी फ़ाइलों के लिए File::Slurp का उपयोग करता हूं, जिन्हें मैं पूरी तरह से स्मृति में रखना चाहता हूं, और Tie::File बड़ी फ़ाइलों के लिए जिन्हें मैं स्केलेबल रूप से संबोधित करना चाहता हूं और/या उन फ़ाइलों को जिन्हें मैं स्थानांतरित करना चाहता हूं।

12

हर जगह 'या मरने' लिखने के बाद मुझे पागल हो जाता है। एक फ़ाइल खोलने के लिए मेरे पसंदीदा तरीका इस तरह दिखता है:

use autodie; 

open(my $image_fh, '<', $filename); 

है कि बहुत कम टाइपिंग है, वहाँ महत्वपूर्ण बातों का एक बहुत कुछ नोट करने के लिए जिस पर जा रहे हैं कर रहे हैं:

  • हम प्रयोग कर रहे हैं autodie प्राग्मा, जिसका अर्थ है कि अगर कुछ गलत हो जाता है तो पर्ल के अंतर्निहित सभी अपवाद फेंक देंगे। यह आपके कोड में or die ... लिखने की आवश्यकता को समाप्त करता है, यह मित्रवत, मानव-पठनीय त्रुटि संदेश उत्पन्न करता है, और इसमें अक्षीय दायरा है। यह सीपीएएन से उपलब्ध है।

  • हम खुले के तीन-तर्क संस्करण का उपयोग कर रहे हैं। इसका मतलब है कि यहां तक ​​कि अगर हमारे पास <, > या | जैसे वर्णों वाला एक मजेदार फ़ाइल नाम है, तो पर्ल अभी भी सही काम करेगा। ओएसकॉन में मेरे पर्ल सुरक्षा ट्यूटोरियल में मैंने दुर्व्यवहार करने के लिए 2-तर्क open प्राप्त करने के कई तरीके दिखाए। इस ट्यूटोरियल के लिए नोट free download from Perl Training Australia के लिए उपलब्ध हैं।

  • हम एक स्केलर फ़ाइल हैंडल का उपयोग कर रहे हैं। इसका मतलब यह है कि हम संयोग से किसी अन्य नाम के किसी अन्य फ़ाइल हैंडल को बंद नहीं कर रहे हैं, जो तब हो सकता है जब हम पैकेज फ़ाइल हैंडल का उपयोग करते हैं। इसका अर्थ यह भी है कि strict टाइपो स्पॉट कर सकता है, और यदि यह दायरे से बाहर हो जाता है तो हमारी फ़ाइल हैंडल स्वचालित रूप से साफ़ हो जाएगी।

  • हम अर्थपूर्ण फ़ाइल हैंडल का उपयोग कर रहे हैं। इस मामले में ऐसा लगता है कि हम एक छवि को लिखने जा रहे हैं।

  • फ़ाइल हैंडल _fh के साथ समाप्त होता है। अगर हम इसे नियमित स्केलर की तरह इस्तेमाल करते देखते हैं, तो हम जानते हैं कि यह शायद एक गलती है।

+0

ग्रेट अंतर्दृष्टि के साथ भी पढ़ सकते हैं, धन्यवाद! मैंने कभी भी "खुले" के लिए 3 तर्क विधि नहीं देखी थी - मुझे लगता है कि मुझे इस तरह से पसंद है! धन्यवाद! – BrianH

3

एक पंक्ति

$text = do {local(@ARGV, $/) = $file ; <>}; 

के साथ या एक समारोह

$text = load_file($file); 
sub load_file {local(@ARGV, $/) = @_; <>} 
1

डेमियन कोनवे यह इस तरह से करता है के रूप में चर $ पाठ में पूरी फ़ाइल $ फ़ाइल पढ़ें:

$data = readline!open(!((*{!$_},$/)=\$_)) for "filename"; 

लेकिन मैं आपको यह सलाह नहीं देता हूं।

+0

यह कैसे काम करता है? –

+0

यह $/को अपरिफ (स्लर्प मोड) सेट करता है और \ $ _ से * {""} असाइन करता है; किसी ग्लोब के संदर्भ को निर्दिष्ट करने से संदर्भ के प्रकार के स्लॉट को प्रतिस्थापित किया जाता है, इसलिए $ {""} $ _ के लिए उपनाम है (जिसका मान "फ़ाइल नाम" है)। द! असाइनमेंट के मूल्य को अस्वीकार करता है (1 स्केलर संदर्भ में सूची असाइनमेंट के बाद से आकलन के दाईं ओर तत्वों की संख्या देता है) तो गलत है। खुला झूठा मान "" के रूप में व्यवहार करता है, इसलिए * {""} फाइलहेडल खोलता है, और एक तर्क खुले फ़ाइल नाम को ग्लोब के स्केलर से खोलने के लिए मिलता है। यदि खुले रिटर्न सही हैं, तो रीडलाइन भी दिए गए झूठे का इलाज करती है! * {""} फाइलहेडल के रूप में – ysth

2

|| ऑपरेटर की उच्च प्राथमिकता है, इसलिए परिणाम को "खुला" भेजने से पहले इसका मूल्यांकन किया जाता है ... आपके द्वारा उल्लिखित कोड में, "या" ऑपरेटर का उपयोग करें, और आपके पास यह नहीं होगा मुसीबत।

open INPUT_FILE, "<$input_file" 
    or die "Can't open $input_file: $!\n"; 
संबंधित मुद्दे

 संबंधित मुद्दे