2012-05-24 14 views
6

पढ़ता है मैं fgetcsv() का उपयोग कर एक CSV फ़ाइल से डेटा आयात करने के लिए PHP का उपयोग कर रहा हूं, जो प्रत्येक पंक्ति के लिए एक सरणी उत्पन्न करता है। प्रारंभ में, मैं 1024 में अक्षरों की सीमा सेट था, इसलिए जैसे:सुनिश्चित करें कि fgetcsv() पूरी लाइन

while ($data = fgetcsv($fp, 1024)) { 
    // do stuff with the row 
} 

हालांकि, एक सीएसवी 200 कॉलम कई पंक्तियों पर 1024 की सीमा को पार कर के साथ। इसने लाइन को पंक्ति के बीच में रोकने के लिए पढ़ा, और फिर fgetcsv() को अगली कॉल शुरू हो जाएगी जहां पिछला एक छोड़ दिया गया था और तब तक जब तक कोई ईओएल नहीं पहुंचा।

मैंने इस सीमा को 4096 तक बढ़ा दिया है, जो कि अधिकांश मामलों का ख्याल रखना चाहिए, लेकिन मैं यह सुनिश्चित करने के लिए एक चेक डालना चाहता हूं कि प्रत्येक पंक्ति के बाद पूरी लाइन पढ़ी जाए। यह कैसे करना है?

मैं रेखा वर्णों (\ n, \ r, \ r \ n) के अंत के लिए सरणी के अंतिम तत्व के अंत की जांच करने के लिए सोच रहा था, लेकिन इन्हें fgetcsv() कॉल द्वारा पार्स नहीं किया जाएगा ?

+0

इसके अलावा, मुझे एहसास है कि मैं प्रोग्राम में प्रोग्राम की सबसे लंबी लाइन निर्धारित कर सकता हूं, लेकिन यह वास्तव में बड़ी सीएसवी फाइलों पर बहुत अधिक ओवरहेड हो सकता है। यह सुनिश्चित करना चाहते हैं कि फ्लाई पर पूरी तरह से प्रत्येक पंक्ति को पढ़ा जाए। –

उत्तर

1

सुझावों के लिए धन्यवाद, लेकिन इन समाधानों ने वास्तव में यह जानने के मुद्दे को हल नहीं किया कि हम अभी भी सीमा प्रदान करते समय सबसे लंबी लाइन के लिए खाते हैं। लाइन 0 लाने से पहले फ़ाइल में सबसे लंबी लाइन निर्धारित करने के लिए wc -L यूनिक्स कमांड shell_exec() के माध्यम से मैं इसे पूरा करने में सक्षम था। कोड के नीचे है:

// open the CSV file to read lines 
$fp = fopen($sListFullPath, 'r'); 

// use wc to figure out the longest line in the file 
$longestArray = explode(" ", shell_exec('wc -L ' . $sListFullPath)); 
$longest_line = (int)$longestArray[0] + 4; // add a little padding for EOL chars 

// check against a user-defined maximum length 
if ($longest_line > $line_length_max) { 
    // alert user that the length of at least one line in the CSV is too long 
} 

// read in the data 
while ($data = fgetcsv($fp, $longest_line)) { 
    // do stuff with the row 
} 

यह दृष्टिकोण सुनिश्चित करता है कि हर पंक्ति अपनी संपूर्णता में पढ़ा जाता है और अभी भी लाइन द्वारा पीएचपी लाइन के साथ पूरी फ़ाइल के माध्यम से कदम के बिना वास्तव में लंबी लाइनों के लिए एक सुरक्षा तंत्र प्रदान करता है।

6

बस लंबाई पैरामीटर को छोड़ दें। यह PHP5 में वैकल्पिक है।

while ($data = fgetcsv($fp)) { 
    // do stuff with the row 
} 
3

बस एक सीमा निर्दिष्ट न करें, और fgetcsv() पूरी लाइन को कैप्चर करने के लिए जितना आवश्यक हो उतना धीमा हो जाएगा। यदि आप एक सीमा निर्दिष्ट करते हैं, तो फ़ाइल स्ट्रीम को स्कैन करने के लिए यह पूरी तरह से आपके ऊपर है और सुनिश्चित करें कि आप बीच में कुछ टुकड़ा नहीं कर रहे हैं।

हालांकि, ध्यान दें कि सीमा को निर्दिष्ट नहीं करना जोखिम भरा हो सकता है यदि आपके पास पहली बार .csv की पीढ़ी पर नियंत्रण नहीं है। अपने सर्वर को एक दुर्भावनापूर्ण CSV के साथ स्वैप करना आसान होगा जिसमें एक पंक्ति पर डेटा के कई टेराबाइट हैं।

+0

मैंने इसे माना, लेकिन 2 चीजें: 1) मेरे पास सीएसवी पीढ़ी पर नियंत्रण नहीं है। वे (अविश्वसनीय) ग्राहकों द्वारा प्रदान किए जाते हैं, इसलिए मैं वास्तव में कुछ प्रकार की सीमा लागू करना चाहता हूं। 2) मैनुअल कहता है "इस पैरामीटर को छोड़कर (या PHP 5.0.4 और बाद में इसे 0 पर सेट करना) अधिकतम लाइन लंबाई सीमित नहीं है, जो थोड़ा धीमा है।" मुझे डर है कि "थोड़ा धीमा" एक सीएसवी फ़ाइल के साथ जोड़ देगा जिसमें 100k + पंक्तियां होंगी। –

+2

थोड़ा धीमा = फाइलों को तब तक पढ़ता है जब तक कि उस हिस्से में कहीं भी एक लाइनब्रेक नहीं मिलता है, फिर फ़ाइल पॉइंटर को रिवाइंड करता है ताकि अगला पठन ब्रेक के बाद सही हो सके। –

+1

आप अलग-अलग लाइन-बाय-लाइन रीडिंग अलग-अलग कर सकते हैं, फिर csv-> सर पार्सिंग करने के लिए [str_get_csv()] (http://php.net/manual/en/function.str-getcsv.php) का उपयोग करें । –

0

मैं आपके अंतिम समाधान से सावधान रहूंगा। मैं आदेश इंजेक्शन करने के लिए /.;ls -a;.csv नाम की एक फ़ाइल अपलोड करने में सक्षम था। यदि आप इस दृष्टिकोण का उपयोग करते हैं तो सुनिश्चित करें कि आप फ़ाइल पथ को मान्य करते हैं। इसके अलावा, आपके wc किसी भी कारण से विफल होने पर default_length प्रदान करना एक अच्छा विचार हो सकता है।

// use wc to find max line length 
// uses a hardcoded default if wc fails 
// this is relatively safe from command 
// injection since the file path is a tmp file 
$wc = explode(" ", shell_exec('wc -L ' . $validated_file_path)); 
$longest_line = (int)$wc[0]; 
$length = ($longest_line) ? $longest_line + 4 : $default_length; 
संबंधित मुद्दे