Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Wczytanie pliku billingu w text
Forum PHP.pl > Forum > PHP
pianta_d
Witam

Stanąłem przed problemem wczytania pliku z bilingiem telefonicznym.
Na późniejszym etapie będę wrzucał to do bazy, ale z tym to nie ma żadnego problemu, natomiast nie wiem jak w ogóle się do tego zabrać.
Plik bilingu ma straszną strukturę.

Przykładowy plik bilingu

Takich stron może być kilkanaście. Oddzielone są od siebie liniami ze znaku "-"
W kolumnie połączenie mogą być inne wpisy niż "lokalne" (ale to już nie jest istotne)

Nie będę się rozpisywał co musi być w skrypcie, aby później wczytać to do bazy.
Proszę o wskazówki.

Pozdrawiam
nospor
No coż, bez wyrażeń się raczej nie obejdzie.

Wydaje mi się, że najlepiej najpierw rozbić plik na konkretne bilingi. Skoro rodzielone one będą --------- to użyć do tego można preg_split()
Mając już konkretny biling, pobierać informacje z niego będziesz przy pomocy preg_match().
abort
Etam, od razu "rozbijać". Zakładam, że interesują nas TYLKO rozmowy. A wszystkie rozmowy (i tylko rozmowy, bez podsumowań pokaże jeden preg_match na [0-9\ ][0-9]:[0-9][0-9]:[0-9][0-9] (uwaga na dołożoną spację w pierwszych [] exclamation.gif!)

Potem tylko rozbić na pola (ciut więcej zabawy będzie z czasem) i wrzucać do bazy.

Oczywiście nagiąłem założenie: powinien nas interesować także numer telefonu, z którego te rozmowy zostały przeprowadzone: zakładam, że to jest to wyiksowane pole tuż przed zestawieniem. Tu wystarczy nawet explode.
pianta_d
Póki co napisałem

  1. $plik = file('plik.txt');
  2. for($i = 55, $x = count($plik); $i < $x; $i++)
  3. {
  4. $str = $plik[$i];
  5. $chars = preg_split('/ /', $str, 0, PREG_SPLIT_NO_EMPTY);
  6. if ($i==55) // nr lini, w której przechowywane są dane do nagłówka
  7. {
  8. echo '<br>Dane bilingowe za okres od '.str_replace('r.','',$chars[7]).' do '.str_replace('r.','',$chars[9]).' z nr tel.
  9. '.$chars[12],$chars[13],$chars[14].'<BR><br>';
  10. }
  11. if ($i >= 60)
  12. {
  13. $ile_kropek=strstr($chars[0], ".");
  14. if ($ile_kropek==TRUE)
  15. {
  16. $data_rozmowy=$chars[0];
  17. echo 'Wstawiamy w pierwszą kolumnę datę, czyli: <b>'.$data_rozmowy.'</b>';
  18. echo ' O godzinie '.$chars[1];
  19. echo ' Na numer '.$chars[2];
  20. echo ' Rodzaj połączenia '.$chars[3].'<br>';
  21. }
  22. else
  23. {
  24. echo 'Kropek brak, ale wstawiamy ze zmiennej, czyli: '.$data_rozmowy.'<br>';
  25. }
  26. }
  27. }

Kod jest z moimi tekstami, które może sa prozaiczne, ale lubię prostotę smile.gif

Ładnie dzieli mi na odpowiednie komórki, które później będą dodawane do bazy.

Cytat
Etam, od razu "rozbijać". Zakładam, że interesują nas TYLKO rozmowy


Generalnie chodzi mi o wszystkie dane zawarte w pliku

Dziękuje za zainteresowanie.
Temat dalej będzie kontynuowany.

Pozdrawiam
Uriziel01
Tak może być ? Kod jest zrobiony 'na kolanie', na pewno można to zrobic jeszcze tysiąc razy lepiej i pewnie zawiera jeszcze 500 błędów ale działa smile.gif Mam dzisiaj dobry humor.
EFEKT:


KOD:
  1. <?PHP
  2. $last_date = NULL;
  3. $plik = file_get_contents('plik.txt');
  4. $plik = get_string_between($plik, 'za okres od','Razem');
  5. $plik = explode("\r\n",$plik);
  6. $numer_linii = substr($plik[0], strpos($plik[0], 'nr linii: ') + 10);
  7. $plik = array_slice($plik,5,-2);
  8. foreach ($plik AS $main_index => &$rozmowa)
  9. {
  10. $rozmowa = ltrim ( $rozmowa, " ");
  11. $rozmowa = explode(" ",$rozmowa);
  12. foreach ($rozmowa AS $index => $pole)
  13. {
  14. if (strlen($pole) < 2)
  15. {
  16. unset($rozmowa[$index]);
  17. }
  18. }
  19. $rozmowa = array_values($rozmowa);
  20. if (strpos($rozmowa[0], " ") !== false)
  21. {
  22. $result[$main_index]['date'] = substr($rozmowa[0], 0, strpos($rozmowa[0], " "));
  23. $result[$main_index]['time'] = substr($rozmowa[0], strpos($rozmowa[0], " "));
  24. }
  25. else
  26. {
  27. if (strpos($rozmowa[0],'.') === false)
  28. {
  29. $result[$main_index]['date'] = $last_date;
  30. $result[$main_index]['time'] = $rozmowa[0];
  31. }
  32. else
  33. {
  34. $result[$main_index]['date'] = $rozmowa[0];
  35. }
  36. }
  37. $last_date = $result[$main_index]['date'];
  38. $result[$main_index]['phone_number'] = $rozmowa[1];
  39. $result[$main_index]['call_type'] = $rozmowa[2];
  40. $result[$main_index]['call_time'] = $rozmowa[3];
  41. $result[$main_index]['netto'] = $rozmowa[4];
  42. $result[$main_index]['brutton'] = $rozmowa[5];
  43. }
  44. var_dump($result);
  45. echo 'NR linii:' . $numer_linii;
  46. function get_string_between($string, $start, $end)
  47. {
  48. $string = " ".$string;
  49. $ini = strpos($string,$start);
  50. if ($ini == 0) return "";
  51. $ini += strlen($start);
  52. $len = strpos($string,$end,$ini) - $ini;
  53. return substr($string,$ini,$len);
  54. }
  55. ?>
abort
Potestuj wyrażenia regularne - to skraca kod:

  1. $rozmowy = array ();
  2. $rozm_idx = 0;
  3. print "<pre>\n"; // dla wygody debugowania
  4. $handle=fopen ("billing.txt", "r"); // zakładamy że plik istnieje,więc brak obsługi błędów
  5. while (!feof ($handle)) {
  6. $line = fgets ($handle, 200);
  7. if (preg_match ('@za okres od\s+([0-9.]+)r. do\s+ ([0-9.]+)r.\s+nr linii: ([0-9x\ \(\)]+).*@', $line, $match)) {
  8. $rozmowy['header']['okres_start']=$match[1];
  9. $rozmowy['header']['okres_end']=$match[2];
  10. $rozmowy['header']['phone_number']=$match[3];
  11. }
  12. if (preg_match ('@([0-9 ]{2}.[0-9]{2}){0,1}\s([0-9 ]{2}.[0-9]{2}.[0-9]{2})\s([0-9x\ \(\)]+)\s+(\w+)\s+([0-9 ms]+)\s+([0-9.,]+)\s+([0-9.,]+)@', $line, $match)) {
  13. $rozm_idx++;
  14. if ($match[1] == '') {
  15. $rozmowy[$rozm_idx]['date']=$rozmowy[$rozm_idx-1]['date'];
  16. } else {
  17. $rozmowy[$rozm_idx]['date']= $match[1];
  18. }
  19. $rozmowy[$rozm_idx]['time']= $match[2];
  20. $rozmowy[$rozm_idx]['phone_number']= $match[3];
  21. $rozmowy[$rozm_idx]['call_type']= $match[4];
  22. $rozmowy[$rozm_idx]['call_time']= $match[5];
  23. $rozmowy[$rozm_idx]['netto']= $match[6];
  24. $rozmowy[$rozm_idx]['brutto']= $match[7];
  25. }
  26. }
  27. fclose ($handle);
  28.  
  29. print_r ($rozmowy); // debug :)
  30.  


Starałem się intuicyjnie nazywać zmienne. Potestuj.
pianta_d
Dziękuje Wam wszystkim.
Cóż, dostałem gotowca i się z tego cieszę, aczkolwiek teraz muszę zrozumieć wyrażenia regularne.
Lektura z internetu jest troszkę chaotyczna i jak na moje lata mało zrozumiała.

Dziękuję jeszcze raz za zainteresowanie i odwdzięczam się jak tylko mogę.

--- EDIT ---

Zauważyłem jeden problem w wyrażeniu regularnym, które napisał @abort. (chłopak nie wiedział, że taka może być sytuacja - w załączonym pliku tego nie ma)
Przy typie połączenia (w pliku mogą być wpisy: "lokalne","KRAKÓW","PLUS GSM", itp.) nie wczytuje połączeń, gdzie typ składa się z dwóch członów, czyli z trzech przytoczonych przykładów wczyta dwa pierwsze wiersze, a pominie "PLUS GSM".

Dzisiaj już siły mi brak, ale jutro siądę nad tym i będę mógł przy okazji poćwiczyć to czego się uczyłem od wczoraj.

Pozdrawiam

---- EDIT ----

Siedzę nad wyrażeniem i przerobiłem to co napisał @abort
  1. preg_match ('@([0-9 ]{2}.[0-9]{2}){0,1}\s([0-9 ]{2}.[0-9]{2}.[0-9]{2})\s([0-9x\ \(\)]+)([a-zA-Z ]{1,}[^s0-9])([0-9 sm]+)\s+([0-9.,]+)\s+([0-9.,]+)@', $line, $match)

wczytuje mi już dwuczłonowe typy połączeń jednak coś pomija.
Podpinam do wczytania plik, na którego końcu jest podsumowanie, gdzie napisano, że abonent wykonał 695 połączeń, a mój preg_match wczytuje mi 647.

Proszę o pomoc z tym wyrażeniem.
zegarek84
na pewno Ci pomija "KRAKÓW" gdyż nie widzę polskich znaków w zestawie znaków...

co do wyrażeń regularnych jest wiele dobrych stron (także manual PHP)... z polskich artykułów co na szybko przychodzi mi do głowy i nie jest najgorszy to:
Wyrażenia regularne PCRE w PHP Tutorial - w nowej wersji PHP dodali jeszcze kilka w sumie zbędnych szczegółów...
abort
Zamiast (\w+) daj coś, co zadziała dla dwóch wyrazów:
Kod
(\w+(\s{1}\w+){0,1})


Tylko indeksy Ci się rozjadą, użyj:
  1. $rozmowy[$rozm_idx]['call_time']= $match[6];
  2. $rozmowy[$rozm_idx]['netto']= $match[7];
  3. $rozmowy[$rozm_idx]['brutto']= $match[8];

Nie ma indeksu "$match[5]".
A precyzyjniej: jest, ale nie do końca pokazuje to, co chcesz. A co pokazuje? Sprawdź, zapewne dojdziesz, dlaczego.

P.S.
W "([0-9x\ \(\)]+)" usuń znak "x" - on był po to, by łapać Twoje wyiksowane (zaciemnione) numery - normalnie tam powinny być cyfry, spacje i nawiasy, iksa tam nie będzie chyba nigdy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.