Php csv dosyasına veri yazma. PHP: Büyük CSV dosyalarının satır satır okunması ve işlenmesi. PHP'de CSV verilerini içe ve dışa aktarma

  • 20.06.2020

Yeterince yüksek, müşteriler yapmak istiyor mal ithalatı onların fiyat listelerinden. Sadece siteye yeni bir ürün ekleyebilmeleri değil, aynı zamanda depodaki mevcut ürünlerin fiyatlarını ve miktarını da güncelleyebilmeleri gerekiyor.

PHP'nin yapabileceği bilinmiyor excel dosyalarıyla çalışma standart anlamına gelir. Elbette excel'de bilgi okuyup yazabilen birçok farklı sınıf var ama bunlarla ilgili bir çok problem var (bunun hakkında ilerideki yazılarda yazacağız).

Çok daha kolay ve daha uygun csv dosyalarıyla çalışma.

Örneğin küçük bir program yapalım. OX2.ru çalışanlarının csv dosyasını işleyecektir.

Excel'de aşağıdaki alanları içeren yeni bir elektronik tablo oluşturalım:

Tabloyu ";" alan ayırıcısı ile csv dosyası olarak kaydedelim.

Bunun gibi bir dosyamız olmalı:

"Ivanov A.A."; "OX2.ru şirketinin programcısı"; 89255552332 "Sidorov A.E."; "OX2.ru şirketinin tasarımı"; 89161231212 "Pirozhkov A.B."; "OX2.ru'nun sanat yönetmeni"; 84951232121 "Kulibin BA "; "Yönetici OX2.ru"; 89031233333

Aşağıda ayrıntılı bir açıklama ile kaynak kodudur.

Kod OOP ile yazılmıştır. sınıfları kullanmak ve küçük bir değişiklikle çeşitli uygulamalarda yeniden kullanılabilir. Sınıflarda programlamaya alışkın değilseniz, ancak işlevleri veya başka bir şeyi kullanıyorsanız, yeniden eğitim almanızı şiddetle tavsiye ederiz))

Kod ayrıca istisnaların oluşturulmasını da kullanır (İstisna), sonraki makalelerimizde onlar hakkında okuyun.

_csv_file = $ csv_file; // Dosyanın yolunu bir değişkene yazın) else (// Dosya bulunamazsa bir istisna atın yeni İstisna atmak ("Dosya" $ csv_file "bulunamadı");)) genel işlev setCSV (Dizi) $ csv) (// csv'yi ön kayıt için aç, // w'yi belirtirsen, csv'deki bilgilerin üzerine yazılır $ handle = fopen ($ this -> _ csv_file, "a"); foreach ($ csv $ değeri olarak) (// Diziyi geçiyoruz // Yazıyoruz, 3. parametre alan ayırıcıdır fputcsv ($ handle, patlat (";", $ value), ";");) fclose ($ handle) ); // Kapat) / ** * csv- dosyasından okuma yöntemi. csv * @return dizisindeki verileri içeren bir dizi döndürür; * / public function getCSV () ($ handle = fopen ($ this -> _ csv_file, "r"); // Okumak için csv'yi açın $ array_line_full = array (); // Dizi, csv'den gelen verileri depolayacaktır // Tüm csv -dosyasını gözden geçirin ve satır satır okuyun 3. parametre alan ayırıcı while (($ satır = fgetcsv ($ tutamaç, 0, ";"))! == YANLIŞ) ($ array_line_full = $ satır; // Satırları diziye yaz) fclose ($ tanıtıcı); // Dosyayı kapat return $ array_line_full; // Okunan verileri döndür)) dene ($ csv = new CSV ("ox2.csv"); // csv'mizi aç / ** * CSV'den oku (ve ekrana güzel çıktı) * / echo "

Kayıttan önce CSV:

"; $ get_csv = $ csv-> getCSV (); foreach ($ değeri olarak $ get_csv) (// Satırlarda döngü eko" Ad: ". $ değer."
"; echo" Başlık: ". $ değer."
"; echo" Telefon: ". $ değer."
"; Eko" --------
";) / ** * CSV'ye yeni bilgi yazma * / $ dizi = dizi (" Antonov BA; Yönetici OX2.ru; 89031233333 "," Kolobkov VB; Patron OX2.ru; 89162233333 "); $ csv-> setCSV ( $ arr);) catch (Exception $ e) (// csv dosyası yoksa, "Error:" mesajını görüntüleyin. $ e-> getMessage ();)?>

CSV dosyalarıyla yapılan ana çalışma sınıf tarafından üstlenilir CSV Aşağıdaki yöntemlere sahiptir:

setCSV (Dizi $ csv)- verileri bir csv dosyasına yazar. Veriler bir dizide aktarılmalıdır. Yöntem bir csv dosyası ekleyebilir ve yeni bir tane oluşturabilir (açıklamayı okuyun).

Yöntem GetCSV csv dosyasından veri okur ve aşağıdaki gibi iki boyutlu bir dizi döndürür:

Dizi (=> Dizi (=> Ivanov A.A. => OX2.ru şirketinin programcısı => 89255552332) => Dizi (=> Sidorov A.E. => OX2.ru şirketinin tasarımı => 89161231212) => Dizi ( => Pirozhkov AB => OX2.ru Sanat Yönetmeni => 84951232121) => Dizi (=> Kulibin BA => OX2.ru Müdürü => 89031233333))

Çok fazla kod ortaya çıkmasına rağmen, örnek oldukça basittir.

csv dosyalarından veri içe aktarma sadece çevrimiçi mağazalardaki ürünleri güncellemek için değil, aynı zamanda normal bir web sitesinde herhangi bir bilgiyi yüklemek / güncellemek için de faydalı olacaktır.

Örneğin, biz siteyi geliştirdi yönetim şirketi ve sıcak ve soğuk su sayaçları ile ilgili bilgileri aylık olarak yayınlamaları gerekiyordu. Tüm verileri excel dosyalarında saklanır. Ve burada csv formatı mükemmeldi!

Aynı zamanda, bir site oluşturmanın maliyeti değişmeyecek ve sitenin işlevselliği ve otomasyonu, rakiplerinden daha yüksek bir seviye olacaktır.

CSV verilerini içe aktarma, sıralama ve dışa aktarma ile ilgili PHP ayrıştırıcılarının geliştirilmesinden birkaç pratik görevi daha analiz edelim. Genellikle ayrıştırma sonuçlarının bir CSV dosyası biçiminde sunulması gerekir, ardından böyle bir dosya sitenin veritabanına aktarılabilir. CSV veri aktarıcıları genellikle çeşitli CMS'nin standart araçları tarafından desteklenir.

CSV (Virgülle Ayrılmış Değerler) Tablo verilerini temsil etmek için tasarlanmış bir metin biçimidir. Ad, verilerin virgülle ayrıldığını belirtir, ancak noktalı virgül (DSV biçimi) gibi diğer ayırıcılar kullanılabilir.

CSV dosyaları, EXCEL programının yanı sıra çeşitli metin düzenleyicilerle açılabilir. Ancak kodlama ile ilgili sorunlar var. Örneğin, EXCEL, BOM olmadan UTF-8'i sindirmede iyi değildir. EXCEL altında, verileri UTF-8'e kaydetmeniz yeterlidir.

Test probleminde, bir dizi CSV dosyasını e-posta sütununa göre sıralamamız gerekiyor. Dosyalar, çeşitli iletişim bilgilerine sahip kuruluşların listelerini içerir ve tüm firmaların e-postası yoktur. Bu nedenle listelerle çalışmayı kolaylaştırmak için listeleri bir komut dosyası ile sıralamak ve iyi bilinen posta kutularına sahip şirketleri en üste koymak uygundur.

Senaryo index.php ve giriş verilerinin bulunduğu dizin klasöre yerleştirilmelidir. csv-sıralayıcı.

İşlenen dosyalar dizine yazılacak çıktı.

PHP'de CSV verilerini içe ve dışa aktarma

index.php dosyasının listelenmesi

CSV dosyalarını alan tamamlamaya göre sıralama

CSV dosyalarını sıralama

sayım ($ satır)) ($ fark = sayım ($ başlık) - sayım ($ satır); for ($ i = 1; $ i<= $difference; $i++) { $row = ""; } } } if($row != "sep=") { $data = $row; } } fclose($handle); } return $data; } /** * Функция сортировки массива по 1-му полю или N полей * * @param string|array $keys, string $order * * @return int */ function sort_arr_ncol($keys, $order = "ASC") { $order = ($order == "DESC") ? -1: 1; if(is_array($keys)) { //если сортировка по нескольким полям return function($a, $b) use ($keys, $order) { foreach($keys as $k) { if($a[$k] != $b[$k]) { return $order * (($a[$k] < $b[$k]) ? 1: -1); } } return 0; }; } else { //если сортировка по одному полю return function($a, $b) use ($keys, $order) { if ($a[$keys] == $b[$keys]) { return 0; } return $order * (($a[$keys] < $b[$keys]) ? 1: -1); }; } } /** * Функция преобразования массива в строку в CSV формате * * @param @param string $input, int $file_size, string $delimiter, string $enclosure * * @return string */ function str_putcsv($input, $file_size, $delimiter = ";", $enclosure = """) { // Open a memory "file" for read/write... $fp = fopen("php://temp", "r+"); // ... write the $input array to the "file" using fputcsv()... fputcsv($fp, $input, $delimiter, $enclosure); // ... rewind the "file" so we can read what we just wrote... rewind($fp); // ... read the entire line into a variable... $data = stream_get_contents($fp); // ... close the "file"... fclose($fp); // ... and return the $data to the caller, with the trailing newline from fgets() removed. return $data; //rtrim($data, "\r"); } // Параметры сортировщика $data_dir_name = "input"; // Каталог с исходными файлами $res_dir_name = "output"; // Каталог с отсортированными файлами $key_list_str = "email"; // Название столбца для сортировки (с нуля) if(!empty($_REQUEST["action"]) && $_REQUEST["action"] = "run") { if(!isset($_REQUEST["charset"])) { $charset = "no"; } else { $charset = $_REQUEST["charset"]; } $k = 0; $er = 0; $error_file_names = array(); $all_file_count = 0; $entries = scandir($data_dir_name); foreach($entries as $entry) { if(mb_strpos($entry, ".csv") !== false) { // Обрабатываем только CSV файлы $filepath_in = $data_dir_name . "/" . $entry; $file_size = filesize($filepath_in); $csv_data_arr = csv2array($filepath_in, $file_size); $header_arr = array_shift($csv_data_arr); $key_list = array_keys($header_arr, $key_list_str); usort($csv_data_arr, sort_arr_ncol($key_list, "ASC")); $csv_data_arr = array_merge($header_arr, $csv_data_arr); // Формируем строку для CSV файла $res_csv_file = ""; foreach($csv_data_arr as $key_row =>$ csv_data_arr_row) ($ res_csv_file. = str_putcsv ($ csv_data_arr_row, $ file_size);) if ($ karakter kümesi == "evet") ($ res_csv_file = iconv ("WINDOWS-1251", "UTF-8", $ res_cs if () $ res_csv_file == false) ($ res_csv_file = iconv ("WINDOWS-1251", "UTF-8 // IGNORE", $ res_csv_file); $ error_file_names = $ giriş;)) $ filepath_out = $ res_dir_name. "/". $ girişi; file_put_contents ($ filepath_out, $ res_csv_file)? $ k ++: $ er ++; $ all_file_count ++; )) Eko "
İşlenen dosyalar: ". $ K." ". $ All_file_count."'dan. Hatalar: ".$ Er."
"; Eko"

". içe doğru ("

", $ error_file_names)."

"; } ?> :: Başlatmak...


Çalışma algoritması aşağıdaki gibidir. Dosyalar belirtilen dizinden okunur. Ardından, veriler CSV formatından PHP dizisine dönüştürülür - bu aslında bir CSV içe aktarımıdır.

İşlev csv2array ($ filepath_in, $ file_size) bir dosyadan CSV verilerini okur ve standart bir PHP işlevi kullanarak onu bir diziye dönüştürür fgetcsv ().

Sıralamadan önce şirketlerin listesi:

csv dosyalarından veri okumak için parseCSV sınıfını kullanıyorum. Bu, csv dosyasını okurken daha fazla esneklik sağlayabilir.

bu denenmemiş ... ancak bunun gibi bir şey hile yapmalı:

$ satır = 1; if (($ tanıtıcı = fopen ("xxxxxxxxx.csv", "r"))! == YANLIŞ) (while (($ veri = fgetcsv ($ tanıtıcı, 1000, ","))! == YANLIŞ) ($ sayı = sayı ($ veri); yankı "

$ satırındaki $ num alanları:

\ n "; $ satır ++; for ($ c = 0; $ c< $num; $c++) { $blackpowder = $data; $dynamit = implode(";", $blackpowder); $pieces = explode(";", $dynamit); $col1 = $pieces; $col2 = $pieces; $col3 = $pieces; $col4 = $pieces; $col5 = $pieces; mysql_query(" INSERT INTO `xxxxxx` (`xxx`,`xxx`,`xxx`,`xxxx`,`xxx`) VALUES ("".$col1."","".$col2."","".$col3."","".$col4."","".$col5."") "); } } }

$ fp = fopen ("ReadMe.csv", "r") veya die ("dosyayı açamıyor"); yazdır"

\ n "; while ($ csv_line = fgetcsv ($ fp, 1024)) (yazdır" "; for ($ i = 0, $ j = say ($ csv_line); $ i< $j; $i++) { print "";) Yazdır"\ n ";) yazdır"
". $ csv_line [$ ben]."
"; fclose ($ fp) or die (" "dosyayı kapatamaz");

Daha fazla detay

Bunu dene….

PHP'de, bir CSV dosyasını okumak ve verilerine erişmek genellikle yararlıdır. Burada fgetcsv() işlevi işe yarar, CSV dosyasının her satırını okuyacak ve her değeri ARRAY dizisine atayacaktır. Bir işlevde bir sınırlayıcı tanımlayabilir ve ayrıca daha fazla seçenek ve örnek için fgetcsv () için PHP belgelerine bakabilirsiniz.

fonksiyon readCSV ($ csvFile) ($ file_handle = fopen ($ csvFile, "r"); while (! Feof ($ file_handle)) ($ line_of_text = fgetcsv ($ file_handle, 1024);) fclose ($ file_handle); return $ line_of_text;) // CSV dosyasının yolunu ayarla $ csvFile = "test.csv"; $ csv = readCSV ($ csvFile); Eko "

"; print_r ($ csv); yankı"
";

Bir CSV dosyasını kullanarak bir diziye ayrıştırmak için bir astar str_getcsv .

$ csv = array_map ("str_getcsv", dosya ("qryWebsite.csv"));

Tüm değerleri anında veritabanına aktaran bir veritabanı sorgusu oluşturmak için:

$ sorgu = "tbl_name (a, b, c) DEĞERLERİNE GİRİN". implode (",", array_map (fonksiyon ($ params) kullanımı (& $ değerleri)) ($ değerler = array_merge ((dizi) $ değerleri, $ params); geri dön "(". implode (",", array_fill ( 0, say ($ params), "?")). ")";), $ csv));

Bu, soru işareti yer tutucularıyla hazırlanmış bir ifade oluşturacaktır, örneğin:

INSERT INTO tbl_name (a, b, c) DEĞERLER (?,?,?), (?,?,?), (?,?,?), (?,?,?)

Ve değişkenler $ değerleri, operatör için değerleri içeren tek boyutlu bir dizi olacaktır. Buradaki uyarılardan biri, csv dosyasının 65.536'dan az giriş içermesi gerektiğidir (maksimum yer tutucu sayısı).

Bir CSV dosyasını bir diziye ayrıştırmak için bir astar

$ csv = array_map ("str_getcsv", dosya ("data.csv"));

Aşağıdaki kodu deneyebilirsiniz. Benim için harika çalışıyor. Daha açık hale getirmek için bir yorumum var. Bu koda bir bağlantı alabilirsiniz.


"; $ kimlik ++;) yankı"

"; fclose ($ tanıtıcı);) // mysql_close ($bağlantı) bağlantısını kapatın; cid = ". $ Id." olan veri girildi Başarıyla


"; $ kimlik ++;) yankı"

Tebrikler tüm veriler başarıyla eklendi

"; fclose ($ handle);) // mysql_close ($ conn) bağlantısını kapatın;

10948 | Kitap | Tip1

SHA512 || 0 || 10948

0 |10948 |SHA512 |

Keşke böyle olsaydı

C3884fbd7fc122b5273262b7a0398e63 | SHA512 | Type1 | Kitap

Gerçek bir veritabanına erişimim yok, bunu yapmanın bir yolu var mı? Temel olarak $ id = $ file1 aranıyor; if ($ dosya3 == $ kimlik) $ kimlik = $ dosya1; if ($ file3 == $ id) veya daha verimli bir şey.

Her CSV dosyası 100k-300k satırları arasında herhangi bir yerdedir. Biraz zaman alması umurumda değil, bir süreliğine EC2'de çalışmasına izin verebilirim.

$ veri = dizi (); $ fh = fopen ("dosya1") or die ("dosya1 açılamıyor"); while (list ($ id, $ değer1, $ değer2) = fgetcsv ($ fh, 0, "|")) ($ veri [$ id] ["değer1"] = $ val1; $ veri [$ id] [" val2 "] = $ val2;) fclose ($ fh); $ fh = fopen ("dosya2") or die ("dosya2 açılamıyor"); while (list ($ method, null, null, null, $ id) = fgetcsv ($ fh, 0, "|")) ($ data [$ id] ["method"] = $ method;) fclose ($ fh ); $ fh = fopen ("file3") veya die ("file3 açılamıyor"); while (list (null, $ id, null, $ hash) = fgetcsv ($ fh, 0, "|")) ($ data [$ id] ["hash"] = $ hash;) fclose ($ fh);

Gerekli, ancak istediğiniz verilerle bir dizi almalısınız. Başka bir csv olarak çıktısını almak, okuyucu için bir alıştırma olarak bırakılmıştır (ipucu: bkz. fputcsv ()).

Her üç dosya da ortak bir alanı paylaşır (örneğin, sizin örneğinizde "10948", üç satırın tümü için ortaktı). Çok fazla bellek kullanma konusunda endişeniz yoksa, paylaşılan bir alanı dizi anahtarı olarak ayarlayarak ve üçünü de toplamak için bir foreach döngüsü kullanarak üç dosyayı da farklı bir diziye yükleyebilirsiniz.

Örneğin:

$ sonuç = dizi(); // Dosya 1 $ fh = fopen ("dosya1"); while (($ veri = fgetcsv ($ fh, 0, "|"))! == YANLIŞ) $ sonuç [$ veri] = $ veri; fclose ($ fh); // Dosya 2 $ fh = fopen ("dosya2") while (($ veri = fgetcsv ($ fh, 0, "|"))! == YANLIŞ) $ sonuç [$ veri] = dizi_merge ($ sonuç [$ veri ], $ veri); fclose ($ fh); // Dosya 3 $ fh = fopen ("dosya3") while (($ veri = fgetcsv ($ fh, 0, "|"))! == YANLIŞ) $ sonuç [$ veri] = dizi_merge ($ sonuç [$ veri ], $ veri); fclose ($ fh);

Temel unix araçlarını kullanarak bir birleştirme sıralaması yapmanızı öneririm:
a) .CSV dosyalarını her dosya için ortak olan sütunlara göre sıralayın, sırala -d "" -K? -İLE? -İLE?
b) .CSV dosyası çiftleri arasında paylaşılan girişleri görüntülemek için unix "join" komutunu kullanmak. "Join" komutu aynı anda yalnızca iki dosyada çalışır, bu nedenle birden çok veri kaynağı için sonuçları "zincirlemeniz" gerekir:

# burada "x", A dosyasındaki alan numarası ve "y", B dosyasındaki alan numarasıdır sıralama -kx "dosyaA" sıralama -ky "dosyaB" birleştirme -1x -2y "dosyaA" "dosyaB"> dosya1 sıralama -kx "fileC" birleştirme -1x -2y "dosya1" "dosyaC"> dosya2 sıralama -kx "dosyaD" birleştirme -1x -2y "dosya2" "dosyaD"> dosya3 vb ...

Çok hızlıdır ve .CSV dosyalarınızı doğaçlama bir veritabanı bağlantısı varmış gibi filtrelemenize olanak tanır.

PHP'de kendi birleştirme-sıralama yönteminizi yazmanız gerekiyorsa: (Buradan Okuyun: Birleştirme Sıralaması)

Dosyaları birleştirmek için en basit uygulama. CSV iki adımdır: a) unix dosyalarınızı sıralar, ardından B) tüm kaynakları paralel olarak "birleştirir", her birinin kayıtlarını okur, ortak alanlarınızdaki değerinizin diğerleriyle eşleştiği bir durum arar kaynaklar (veritabanı terminolojisinde JOIN):
kural 1) Daha az olan girişi atlayın (<) ВСЕХ других источников.
kural 2) Girişin toplam değeri (==) olduğunda, diğer tüm kaynakların bir eşleşmesi vardır.
kural 3) Girdinin toplam değeri (==), başka bir kaynaktan BAZI ise, isterseniz "LEFT-JOIN" mantığını kullanabilirsiniz, aksi takdirde tüm kaynaklardan bu girişi atlayın.

Birden çok dosyayı birleştirmek için sözde kod

Her veri kaynağından 1. kaydı okuyun; "tüm veri kaynaklarından kayıt var" iken; her Veri Kaynağında A için yapın; her Veri Kaynağında B için cntMissMatch = 0 olarak ayarlayın; eğer A.field yap< B.field then cntMissMatch+=1 end if end for if cntMissMatch == count(Data-Sources) then # found record with lowest values, skip it read next record in current Data-source; break; # start over again looking for lowest else if cntMissMatch == 0 then we have a match, process this record; read in next record from ALL data-sources ; break; # start over again looking for lowest else # we have a partial match, you can choose to have # "LEFT-JOIN" logic at this point if you choose, # where records are spit out even if they do NOT # match to ALL data-sources. end if end if end for done

Bu yardımcı olur umarım.