Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: вытащить определенную строку из файла
 
 автор: kaoz   (29.05.2006 в 17:56)   письмо автору
 
 

есть файл состоящий из 300000 строк. (причем длина строки всегда разная, строка заканчивается символом возврата коретки)
как, указав номер строки, получить в переменную $string эту строку.

   
 
 автор: kaoz   (29.05.2006 в 18:13)   письмо автору
 
   для: kaoz   (29.05.2006 в 17:56)
 

.

   
 
 автор: kaoz   (29.05.2006 в 18:45)   письмо автору
 
   для: kaoz   (29.05.2006 в 18:13)
 

возможно ли это?

   
 
 автор: WebTech   (29.05.2006 в 18:49)   письмо автору
 
   для: kaoz   (29.05.2006 в 17:56)
 


<?php

// $str_num - номер строки, нумерация начинается с нуля. Если нумерация с 1, то надо в качестве 
// индекса массива указать $str_num-1
// data.txt - это файл

$lines file("data.txt");

$string $lines[$str_num];

?>

   
 
 автор: kaoz   (29.05.2006 в 19:22)   письмо автору
 
   для: WebTech   (29.05.2006 в 18:49)
 

тада такой вопрос, как сделать вытаскивание всех строк в массив $string[$str_num]?
вопервых до конца файла лезть надо.
вовторых если файл огроменный, к примеру, будет, то фунцией file не рекомендовано пользоваться..

   
 
 автор: Boss   (29.05.2006 в 19:29)   письмо автору
 
   для: kaoz   (29.05.2006 в 19:22)
 

Бред. file() не является безопастной в плане двоичных файлов. А так открывай и считывай в масссив, затем циклом ищи что надо. Что здесь тяжелого?

   
 
 автор: kaoz   (29.05.2006 в 19:24)   письмо автору
 
   для: WebTech   (29.05.2006 в 18:49)
 

тада такой вопрос, как сделать чтение всех строк в массив $string[$str_num]?

1. надо лезть до конца файла
2. если файл большой будет, то это функцией не рекомендованно пользоваться.

   
 
 автор: kaoz   (29.05.2006 в 19:34)   письмо автору
 
   для: kaoz   (29.05.2006 в 19:24)
 

реально погонял эту функцию на файл весом в 103 мб... сервак думает около секунды, что не есть хорошо...

а этих файлов знаешь сколько =)... реально сервак потухнет на сутки =)

   
 
 автор: Trianon   (29.05.2006 в 19:43)   письмо автору
 
   для: kaoz   (29.05.2006 в 19:34)
 

Файлы не меняются? Тогда стройте индексы к файлам.
Либо перегоняйте содержимое в БД.

   
 
 автор: kaoz   (29.05.2006 в 19:51)   письмо автору
 
   для: Trianon   (29.05.2006 в 19:43)
 

два файла в сутки пишуться каждые 15 минут, причем мега на два - три.
цель задачи загнать данные в БД.. файл обрабатывается построчно...

попробовал запустить на серваке функцию для работы с файлом в 103 мб сервер призадумался чуть... а это плохо...

еще нужно решить задачу перегона данных из дописанных файлов и тоже надо обрабатывать построчно... т.е. надо узнать конец файла и от начала парпарсить все строки. как в случае с данным вариантом поступить?

   
 
 автор: Trianon   (29.05.2006 в 20:21)   письмо автору
 
   для: kaoz   (29.05.2006 в 19:51)
 

Они каждые 15 минут с нуля перезаписываются до трех метров? Или раз в 15 минут идет дозапись в хвост файла?
Зачем нужен доступ к произвольной строке? Почему нельзя обойтись последовательным?

   
 
 автор: kaoz   (29.05.2006 в 20:59)   письмо автору
 
   для: Trianon   (29.05.2006 в 20:21)
 

дозаписываются в хвост...

нужно брать строку, обрабатывать и переходить к следующей...
причем нужно после дозаписи начинать с того места где закончили.. (15 минут это общий интервал, бывает и 16 бывает и 30 минут, а может и 5... я так понимаю нужно запускать скрипт каждый час и парсить его с того места где остановились, построчно)

если возможно последовательно, то как это реализовать

кста, еще вопрос чем лучше(быстрее) парсить регулярными выражениями или функциями php?

   
 
 автор: Trianon   (29.05.2006 в 21:10)   письмо автору
 
   для: kaoz   (29.05.2006 в 20:59)
 

Открыть файл.
Спозиционироваться в нужную точку функцией fseek. Первый раз позиция этой точки равна нулю.
Потом просто читать файл в цикле с помощью fgets, и обрабатывать данные - заносить в БД, как я понимаю, пока не будет достигнут конец файла.
После этого считать позицию функцией ftell и сохранить её до следующего вызова. В той же базе например.

Лучше будет читать и записывать строки по несколько сотен (или тысяч) строк за раз.
(Где-то на форуме я даже как-то давал пример, как это можно делать.) Процесс при этом ускоряется в десятки-сотни раз.

PS. нашел эту тему ... [url=?id_forum=1&id_theme=14243 ]вот.[/url]

   
 
 автор: kaoz   (30.05.2006 в 12:22)   письмо автору
 
   для: Trianon   (29.05.2006 в 21:10)
 

сделал так:


<?php
$blk_factor 
16538
$handle fopen(FILES_DIR."ISALOG_20060528_FWS_000.iis""r"); 
$block ''
$sep "\n"
while (!
feof($handle)) 

    
$block .= fread($handle$blk_factor); 
    
$lines explode($sep$block); 
    
$cnt count($lines); 
    
    echo 
$cnt."<br \>\n";

    for(
$i=0;$i<$cnt;$i++)
      {
        echo 
"<b>".$i.": </b>";
        echo 
$lines[$i]."<br \>\n"
// вместо эхов должна быть обработка и  занесение в базу.
      
}

fclose($handle); $blk_factor 1000
?>

т.к. длина строки не фиксированная то в блок может невходить часть последней строки... как сделать чтоб он выдирал определенное кол-во строк за раз?

и можно сделать так чтоб в базу за один запрос загналось несколько строк?

   
 
 автор: kaoz   (30.05.2006 в 12:23)   письмо автору
 
   для: kaoz   (30.05.2006 в 12:22)
 

Спозиционироваться в нужную точку функцией fseek. Первый раз позиция этой точки равна нулю.
Потом просто читать файл в цикле с помощью fgets, и обрабатывать данные - заносить в БД, как я понимаю, пока не будет достигнут конец файла.
После этого считать позицию функцией ftell и сохранить её до следующего вызова. В той же базе например.


можно код привести в пример... а то чето в файлы врубиться немогу :(

   
 
 автор: kaoz   (30.05.2006 в 12:58)   письмо автору
 
   для: kaoz   (30.05.2006 в 12:23)
 

.

   
 
 автор: Trianon   (30.05.2006 в 13:06)   письмо автору
 
   для: kaoz   (30.05.2006 в 12:23)
 


session_start();
$pos = $_SESSION['pos'];

$fp = fopen("file.txt", "rb");

fseek($fp, $pos, SEEK_SET);

while(!feof($fp))
{
  // здесь чтение и обработка.
  $line = fgets($fp); // этот вызов нужно будет поменять на код, который вытаскивает блоки строк
  //......

$pos =  ftell(fp);
$_SESSION['pos'] = $pos;

   
 
 автор: kaoz   (30.05.2006 в 13:11)   письмо автору
 
   для: Trianon   (30.05.2006 в 13:06)
 

ок за этот код спасибо, а как сделать вытаскивание блоков, к примеру, по 100 строк?

   
 
 автор: Trianon   (30.05.2006 в 13:18)   письмо автору
 
   для: kaoz   (30.05.2006 в 13:11)
 

А для Вас принципиально, чтобы именно по 100?
Код под ссылкой занимался именно этим.
Вытаскивал за раз много строк. Сколько поместилось.
Потом все эти строки обрабатывались иодним запросом уходили в базу.
Базе совсем не обязательно, чтобы в нее именно по 100 заливали. База не человек.

   
 
 автор: kaoz   (30.05.2006 в 13:31)   письмо автору
 
   для: Trianon   (30.05.2006 в 13:18)
 

по 100 не принципиально, можно в принципе сделать переменную где указывается сколько строк, хоть одна...

попробовал код под ссылкой, работает но не совсем так как надо...
дело в том что у меня не фиксированная длина строки, и тем кодом очень часто не захватывается последняя строка до конца...
а мне нужно чтобы я указал 100 строк, к примеру и он мне сохранил в массив 100 полных строк..

   
 
 автор: Trianon   (30.05.2006 в 13:47)   письмо автору
 
   для: kaoz   (30.05.2006 в 13:31)
 

Тот код тоже расчитан на переменную длину строки. То, что в примере были одинаковые строки, еще ни о чем не говорит. Я проверял код и на строках произвольной длины.
И начальная часть строки, недочитанной при предыдущем чтении, дописывается в начало буфера при последующем. Так что ничего не пропадает.

Как читать одной операцией конкретное количество строк произвольной длины, я, лично, не знаю. По-моему, это просто неосуществимо.

   
 
 автор: kaoz   (30.05.2006 в 13:54)   письмо автору
 
   для: Trianon   (30.05.2006 в 13:47)
 

то что ничего не пропадает, понятно...

но вот как определять что это продолжение строки и как определить что в этом продолжении?

   
 
 автор: Trianon   (30.05.2006 в 14:01)   письмо автору
 
   для: kaoz   (30.05.2006 в 13:54)
 

Это делали те строки, которые Вы почему-то выбросили:


    $block = $cnt <= 1 || substr($block,-1,1) == $sep 
                 ? "" :   $lines[--$cnt]; 
    if($block != "") 
       unset($lines[$cnt]); 

   
 
 автор: kaoz   (30.05.2006 в 14:11)   письмо автору
 
   для: Trianon   (30.05.2006 в 14:01)
 

я что-то не понял как это работает...
вы не могли бы прокоментировать?

   
 
 автор: Trianon   (30.05.2006 в 14:32)   письмо автору
 
   для: kaoz   (30.05.2006 в 14:11)
 


<?php
$blk_factor 
40000;

$handle fopen($filename"r");   // открываем файл
$block '';  // при первом чтении в буфере предчтения пусто.
$sep "\n";  // строки в файле разделены символом LF
while (!feof($handle))  // пока не достигнем конца файла
{   // дописываем к буферу очередной большой блок макс.размером $blk_factor
    
$block .= fread($handle$blk_factor);
    
// разбиваем блок на строки и помещаем их в массив $lines
    
$lines explode($sep$block);
    
// вычисляем количество строк
    
$cnt count($lines);


    
$block $cnt <= 1     // если строка одна или ни одной, а также если
       
|| substr($block,-1,1) == $sep // последняя строка попала в буфер целиком
        
"" //то мы всё обработаем до конца, и буфер будет пуст.
        
:   $lines[--$cnt]; // иначе обрывок оставим в буфере, а число строк уменьшим
    
if($block != ""//
       
unset($lines[$cnt]); // и удалим обрывок из массива.



    
foreach($lines as $line)
       echo 
$line.'<br>';


}

   
 
 автор: kaoz   (30.05.2006 в 14:39)   письмо автору
 
   для: Trianon   (30.05.2006 в 14:32)
 

т.е. недозаписанная строка попадает в следующий блок?

   
 
 автор: Trianon   (30.05.2006 в 14:41)   письмо автору
 
   для: kaoz   (30.05.2006 в 14:39)
 

Недочитанная, а не недописанная. Да.

   
 
 автор: kaoz   (30.05.2006 в 14:46)   письмо автору
 
   для: Trianon   (30.05.2006 в 14:41)
 

вы меня поняли :)

крута, большое спасибо!!

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования