লাইন দ্বারা একটি বড় ফাইল লাইন পড়তে কিভাবে?


469

আমি লাইন দ্বারা একটি ফাইল লাইন পড়তে চাই, তবে এটি সম্পূর্ণরূপে স্মৃতিতে লোড না করে।

আমার ফাইলটি মেমোরিতে খোলার জন্য খুব বড়, এবং যদি এটি করার চেষ্টা করা হয় আমি সর্বদা স্মৃতি ত্রুটি থেকে বেরিয়ে আসি।

ফাইলের আকার 1 জিবি।



7
আপনার প্যারামিটার fgets()ছাড়াই ব্যবহার করা উচিত $length
কার্লোস

26
আপনি নীচের যে কোনও একটিতে উত্তর হিসাবে চিহ্নিত করতে চান?
কিম স্ট্যাকস

উত্তর:


684

আপনি fgets()লাইন দ্বারা ফাইল লাইন পড়তে ফাংশনটি ব্যবহার করতে পারেন :

$handle = fopen("inputfile.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        // process the line read.
    }

    fclose($handle);
} else {
    // error opening the file.
} 

3
too large to open in memoryঅংশটির জন্য এই অ্যাকাউন্টটি কীভাবে হয় ?
স্টারেক্স

64
আপনি মেমরির পুরো ফাইলটি পড়ছেন না। এটি চালানোর জন্য সর্বাধিক মেমরির প্রয়োজন ইনপুটটির দীর্ঘতম লাইনের উপর নির্ভর করে।
6:54 এ 12

13
@ ব্র্যান্ডিন - মূট - এই পরিস্থিতিতে, লাইন বাই লাইন ফাইল পড়ার জন্য জিজ্ঞাসিত প্রশ্নটির একটি সুসংজ্ঞাযুক্ত ফলাফল নেই।
টুলমেকারস্টেভ

3
@ টুলমেকারস্টেভ তারপরে যা ঘটবে তা নির্ধারণ করুন। আপনি যদি চান তবে আপনি "লাইন খুব দীর্ঘ; ছেড়ে দেওয়া" বার্তাটি মুদ্রণ করতে পারেন। এবং এটি খুব ভাল সংজ্ঞাযুক্ত ফলাফল is
ব্র্যান্ডিন

2
একটি লাইনে কি বুলেটিয়ান মিথ্যা থাকতে পারে? যদি তাই হয় তবে এই পদ্ধতিটি ফাইলের শেষে পৌঁছানো ছাড়াই থামবে। এই ইউআরএল এর # 1 উদাহরণ php.net/manual/en/function.fgets.php পরামর্শ দেয় যে ফাইজেটগুলি কখনও কখনও বুলেটিয়ান মিথ্যা ফিরিয়ে দিতে পারে যদিও ফাইলের শেষ এখনও পৌঁছায়নি। এই পৃষ্ঠার মন্তব্য বিভাগে লোকেরা জানিয়েছে যে fgets () সর্বদা সঠিক মান দেয় না, সুতরাং লুপকে শর্তযুক্ত হিসাবে ফিউফ ব্যবহার করা আরও নিরাপদ।
সিজনহসন

130
if ($file = fopen("file.txt", "r")) {
    while(!feof($file)) {
        $line = fgets($file);
        # do same stuff with the $line
    }
    fclose($file);
}

8
@ কিউজ 70 যেমন তার উত্তরে বলেছে যে ফাইলটি বিদ্যমান না থাকলে বা খোলা না থাকলে এটি অসীম লুপের দিকে পরিচালিত করবে। if($file)লুপের আগে পরীক্ষা করুন
ফ্রান্সেসকোএমএম

10
আমি জানি এটি পুরানো, তবে: (! ফিউফ ($ ফাইল)) ব্যবহার করার প্রস্তাব দেওয়া হয় না। এখানে দেখুন।
কেভিন ভ্যান রিকিজেম

বিটিডাব্লু: "যদি ফাইল পয়েন্টারে পড়ার মতো আরও কোনও ডেটা না থাকে তবে মিথ্যা ফিরিয়ে দেওয়া হবে।" php.net/manual/en/function.fgets.php ... ঠিক সেক্ষেত্রে
প্রত্যেকে

2
feof()আর অস্তিত্ব নেই?
রায়ান ডুভাল

94

আপনি কোনও ফাইলের জন্য একটি অবজেক্ট ওরিয়েন্টেড ইন্টারফেস ক্লাস ব্যবহার করতে পারেন - স্প্লিলফিলঅবজেক্ট http://php.net/manual/en/splfileobject.fgets.php (পিএইচপি 5> = 5.1.0)

<?php

$file = new SplFileObject("file.txt");

// Loop until we reach the end of the file.
while (!$file->eof()) {
    // Echo one line from the file.
    echo $file->fgets();
}

// Unset the file to call __destruct(), closing the file handle.
$file = null;

3
অনেক ক্লিনার সমাধান। ধন্যবাদ;) এই ক্লাসটি এখনও ব্যবহার করেন নি, এক্সপ্লোর করার জন্য এখানে আরও আকর্ষণীয় ফাংশন রয়েছে: php.net/manual/en/class.splfileobject.php
লুকাশ লিসিস

6
ধন্যবাদ। হ্যাঁ, উদাহরণস্বরূপ আপনি line file-> setFlags (SplFileObject :: DROP_NEW_LINE) এর আগে এই লাইনটি যুক্ত করতে পারেন; একটি লাইন শেষে newlines ড্রপ।
elshnkhll

আমি যতদূর দেখতে পাচ্ছি eof()স্প্লিলফিলঅবজেক্টে কোনও ফাংশন নেই ?
Chud37

3
ধন্যবাদ! এছাড়াও, rtrim($file->fgets())প্রতিটি লাইনের স্ট্রিংয়ের জন্য নতুন লাইনগুলি স্ট্রাইপ করার জন্য ব্যবহার করুন যা যদি আপনি না চান তবে পড়ে।
racl101

@ চুদ 37 হ্যাঁ আছে: php.net/manual/en/splfileobject.eof.php
নাথান এফ।

59

আপনি যদি একটি বড় ফাইল খোলেন, আপনি সম্ভবত পুরো ফাইলটিকে মেমোরিতে লোড করতে এড়াতে fgets () এর পাশাপাশি জেনারেটরগুলিও ব্যবহার করতে চান:

/**
 * @return Generator
 */
$fileData = function() {
    $file = fopen(__DIR__ . '/file.txt', 'r');

    if (!$file)
        die('file does not exist or cannot be opened');

    while (($line = fgets($file)) !== false) {
        yield $line;
    }

    fclose($file);
};

এটি এর মতো ব্যবহার করুন:

foreach ($fileData() as $line) {
    // $line contains current line
}

এইভাবে আপনি foreach () এর ভিতরে পৃথক ফাইল লাইন প্রক্রিয়া করতে পারেন।

দ্রষ্টব্য: জেনারেটরের জন্য> = পিএইচপি 5.5 প্রয়োজন


3
পরিবর্তে এটি একটি গ্রহণযোগ্য উত্তর হওয়া উচিত। জেনারেটরগুলির সাথে এটি শতগুণ দ্রুত।
তাচি

1
এবং waaay আরও মেমরি দক্ষ।
নিনো এককাপ্যাক

2
@ নিনোকোপ্যাক: আপনি ব্যাখ্যা করতে পারেন কেন এই সমাধানটি আরও মেমরি-দক্ষ? উদাহরণস্বরূপ, SplFileObjectপদ্ধতির তুলনায় ।
k00ni

30

ফাইলটি পড়ার জন্য বাফারিং কৌশলগুলি ব্যবহার করুন।

$filename = "test.txt";
$source_file = fopen( $filename, "r" ) or die("Couldn't open $filename");
while (!feof($source_file)) {
    $buffer = fread($source_file, 4096);  // use a buffer of 4KB
    $buffer = str_replace($old,$new,$buffer);
    ///
}

2
এটি আরও ভালবাসার দাবি রাখে, কারণ এটি বিশাল ফাইলগুলি এমনকি এমন কোনও ফাইলের সাথেও কাজ করবে যা কোনও গাড়ীতে ফিরে আসে না বা খুব দীর্ঘ লাইন থাকে ...
জিম্মি

যদি ওপি সত্যিকারের লাইনের বিষয়ে যত্ন না করে এবং উদাহরণস্বরূপ একটি ডাউনলোড পরিবেশন করতে চায় তবে আমি অবাক হব না। সেক্ষেত্রে এই উত্তরটি ঠিক আছে (এবং বেশিরভাগ পিএইচপি কোডাররা যাই হোক না কেন)।
vlvaro González

30

একটি file()ফাংশন রয়েছে যা ফাইলে থাকা লাইনগুলির একটি অ্যারে প্রদান করে।

foreach(file('myfile.txt') as $line) {
   echo $line. "\n";
}

28
এক জিবি ফাইল সবই মেমোরিতে পড়বে এবং একাধিক জিবি অ্যারে রূপান্তরিত হবে ... শুভকামনা।
ফ্রান্সেসকোএমএম

4
এটি জিজ্ঞাসা করা প্রশ্নের উত্তর ছিল না, তবে এটি এখানে দেখার সময় অনেক লোকের সাধারণ প্রশ্নের উত্তর দেয়, তাই এটি এখনও কার্যকর ছিল, ধন্যবাদ।
পিলাভডজিস

2
ফাইল () ছোট ফাইলগুলির সাথে কাজ করার জন্য খুব সুবিধাজনক। বিশেষত যখন আপনি শেষ ফলাফল হিসাবে একটি অ্যারে () চান।
functionvoid

বড় ফাইলগুলির সাথে এটি একটি খারাপ ধারণা কারণ পুরো ফাইলটি একবারে একটি অ্যারেতে পঠিত হচ্ছে
ফ্ল্যাশ থান্ডার

এটি বড় ফাইলগুলিতে খারাপভাবে ভেঙে যায়, সুতরাং এটি হ'ল পদ্ধতিটি কার্যকর হয় না।
ftrotter


17

সমস্ত প্রতিক্রিয়া মধ্যে সুস্পষ্ট উত্তর ছিল না।
পিএইচপি-র ঠিক সেই উদ্দেশ্যে তৈরি একটি ঝরঝরে স্ট্রিমিং ডিলিমিটার পার্সার রয়েছে।

$fp = fopen("/path/to/the/file", "r+");
while ($line = stream_get_line($fp, 1024 * 1024, "\n")) {
  echo $line;
}
fclose($fp);

এটি লক্ষ করা উচিত যে এই কোডটি প্রথম খালি লাইনটি না হওয়া পর্যন্ত কেবল রেখাগুলি ফিরে আসবে। আপনাকে $ লাইনের জন্য পরীক্ষা করতে হবে! == অন্যদিকে শর্তে মিথ্যাwhile (($line = stream_get_line($fp, 1024 * 1024, "\n")) !== false)
সেবে

8

'যখন (! Feof ... fgets ()' স্টাফের সাথে সাবধান থাকুন, fgets একটি ত্রুটি পেতে পারে (মিথ্যা প্রত্যাবর্তন করতে পারে) এবং চূড়ান্তভাবে লুপটি ফাইলের শেষে না পৌঁছতে পারে c কোডডডিক্ট সঠিক হওয়ার সবচেয়ে কাছের ছিল তবে যখন আপনার 'যখন fgets' লুপ শেষ হয়, ফিফ চেক করুন; সত্য না হলে আপনার একটি ত্রুটি হয়েছিল।


8

আমি কীভাবে এটি খুব বড় ফাইলের সাথে পরিচালনা করি (100 জি পর্যন্ত পরীক্ষা করা হয়)। এবং এটি fgets () থেকে দ্রুত

$block =1024*1024;//1MB or counld be any higher than HDD block_size*2
if ($fh = fopen("file.txt", "r")) { 
    $left='';
    while (!feof($fh)) {// read the file
       $temp = fread($fh, $block);  
       $fgetslines = explode("\n",$temp);
       $fgetslines[0]=$left.$fgetslines[0];
       if(!feof($fh) )$left = array_pop($lines);           
       foreach ($fgetslines as $k => $line) {
           //do smth with $line
        }
     }
}
fclose($fh);

আপনি কীভাবে নিশ্চিত করবেন যে 1024 * 1024 ব্লকটি লাইনের মাঝখানে না ভেঙে যায়?
ব্যবহারকারী 151496

1
@ ব্যবহারকারী151496 সহজ !! গণনা ... 1.2.3.4
ওমর এল ডন

@ ওমারএলডন আপনার অর্থ কি?
কোডেক্স 73

7

এই প্রশ্নের জনপ্রিয় সমাধানগুলির মধ্যে একটিতে নতুন লাইন চরিত্রটি নিয়ে সমস্যা থাকবে। এটি একটি সহজ সঙ্গে বেশ সহজ সংশোধন করা যেতে পারে str_replace

$handle = fopen("some_file.txt", "r");
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        $line = str_replace("\n", "", $line);
    }
    fclose($handle);
}

6

বড় ফাইলগুলির সাথে ডিল করার ক্ষেত্রে স্প্লিফিলঅবজেক্টটি কার্যকর।

function parse_file($filename)
{
    try {
        $file = new SplFileObject($filename);
    } catch (LogicException $exception) {
        die('SplFileObject : '.$exception->getMessage());
    }
    while ($file->valid()) {
        $line = $file->fgets();
        //do something with $line
    }

    //don't forget to free the file handle.
    $file = null;
}

1
<?php
echo '<meta charset="utf-8">';

$k= 1;
$f= 1;
$fp = fopen("texttranslate.txt", "r");
while(!feof($fp)) {
    $contents = '';
    for($i=1;$i<=1500;$i++){
        echo $k.' -- '. fgets($fp) .'<br>';$k++;
        $contents .= fgets($fp);
    }
    echo '<hr>';
    file_put_contents('Split/new_file_'.$f.'.txt', $contents);$f++;
}
?>

-8

অ্যারে রিটার্ন সহ পড়ার ফাংশন

function read_file($filename = ''){
    $buffer = array();
    $source_file = fopen( $filename, "r" ) or die("Couldn't open $filename");
    while (!feof($source_file)) {
        $buffer[] = fread($source_file, 4096);  // use a buffer of 4KB
    }
    return $buffer;
}

4
এটি মেমরিতে একাধিক গিগাবাইটেরও বেশি একক অ্যারে তৈরি করবে (এটির জন্য সৌভাগ্য) এমনকি লাইনগুলিতে নয় তবে স্বেচ্ছাসেবী 4096 অক্ষর খণ্ডে বিভক্ত। কেন পৃথিবীতে আপনি এটি করতে চান?
ফ্রান্সেসকোএমএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.