Bir CSV dosyası PHP kullanarak başka ama sadece tek veya çift tırnak arasında bir şey ile yeni bir satır değiştirme veya kaldırma

5 Cevap php

300,000 kayıtları - Ben yaklaşık 200.000 tutan bir CSV dosyası var. Kayıtların en basit ile ayrılmış ve bir MySQL veritabanı eklenebilen

$line = explode("\n", $fileData);

ve ve bu değerler ile ayrılmıştır

$lineValues = explode(',', $line);

ve sonra doğru veri türü, yani int, float, string, metin, vb kullanarak veritabanına eklenen

Ancak, bazı kayıtları dizesinde bir \ n içeren bir metin sütun var. Hangi $ hattını kullanırken kırar = ("\ n", $ fileData) patlayabilir; yöntemi. Veritabanına eklenmesi gereken veri her satırı yaklaşık 216 sütun vardır. her satır dize \ n 'ile bir kaydı var. Ancak, \ n doğrultusunda bulunan her zaman o ('), tek bir çift tırnak arasında bulunan

her satırı aşağıdaki biçimde kurulur:

id,data,data,data,text,more data

Örnek:

1,0,0,0,'Hello World,0
2,0,0,0,'Hello
    World',0
3,0,0,0,'Hi',0
4,0,0,0,,0

Eğer örnekte de görebileceğiniz gibi, en kayıtları kolayca yukarıda gösterilen yöntemlerle ayrılabilir. Soruna neden örnekte Onun ikinci rekor.

Yeni hatlar sadece \ n ve dosya tüm dosya \ r içermez.

5 Cevap

If the csv data is in a file, you can just use fgetcsv() as others have pointed out. fgetcsv handles embedded newlines correctly.

Csv veri (sizin örnekte $ Filedata gibi) bir dize ise ancak aşağıdaki yöntemi str_getcsv () bir seferde sadece bir satırda çalışır ve kayıtları içine bir bütün dosyayı bölemezsiniz olarak yararlı olabilir.

Her satırında tırnak sayarak gömülü satırsonlarını algılayabilir. Tırnak bir tek sayı varsa, tamamlanmamış bir çizgi var, bu yüzden aşağıdaki satırı ile bu çizgiyi birleştirin. Eğer tırnak çift sayıda var, tam bir kayıt var.

Eğer tam bir rekor var, (tekrar) (patlayabilir kullanarak) tırnak de bölünmüş. Tek numaralı alanlar (dolayısıyla gömülü virgül özel olmayan) işlem gören, hatta numaralı alanlar değildir.

Örnek:

# Split file into physical lines (records may span lines)
$lines = explode("\n", $fileData);

# Re-assemble records
$records = array ();
$record = '';
$lineSep = '';
foreach ($lines as $line) {
  # Escape @ symbol so we can use it as a marker (as it does not conflict with
  # any special CSV character.)
  $line = str_replace('@', '@a', $line);

  # Escape commas as we don't yet know which ones are separators
  $line = str_replace(',', '@c', $line);

  # Escape quotes in a form that uses no special characters
  $line = str_replace("\\'", '@q', $line);
  $line = str_replace('\\', '@b', $line);

  $record .= $lineSep . $line;
  $lineSep = "\n";

  # Must have an even number of quotes in a complete record!
  if (substr_count($record, "'") % 2 == 0) {
    $records[] = $record;
    $record = '';
    $lineSep = '';
  }
}
if (strlen($record) > 0) {
  $records[] = $record;
}

$rows = array ();

foreach ($records as $record) {
  $chunks_in = explode("'", $record);
  $chunks_out = array ();

  # Decode escaped quotes/backslashes.
  # Decode field-separating commas (unless quoted)
  foreach ($chunks_in as $i => $chunk) {
    # Unescape quotes & backslashes
    $chunk = str_replace('@q', "'", $chunk);
    $chunk = str_replace('@b', '\\', $chunk);
    if ($i % 2 == 0) {
      # Unescape commas
      $chunk = str_replace('@c', ',', $chunk);
    }
    $chunks_out[] = $chunk;
  }

  # Join back together, discarding unescaped quotes
  $record = join('', $chunks_out);

  $chunks_in = explode(',', $record);
  $row = array ();
  foreach ($chunks_in as $chunk) {
    $chunk = str_replace('@c', ',', $chunk);
    $chunk = str_replace('@a', '@', $chunk);
    $row[] = $chunk;
  }
  $rows[] = $row;
}

Burada diğer tavsiye size sadece dışarı veri almak istiyorsanız, fgetcsv() function kullanımı ve uygulanması konusunda endişelenmeyin, ancak, kendi CSV ayrıştırıcı yazmak amacı, özellikle, tabii, geçerli ayrıntıları.

ile nasıl elle, baştan sona, veri yineleme için-döngü ya da iki? Bu explode() daha yavaş, ama tırnak ilişkin tutarlı ve güvenilir sonuçlar elde etmek kolay.

Bu yöntemi seçerseniz, hesaba kaçtı tırnak almak hatırlıyorum.

Eğer bir sayı ile başlayan her yeni çizgi geçerli yeni satır (yani bir metin açıklaması ortasında) olduğunu garanti olabilir, o zaman aşağıdaki gibi bir şey deneyebilirsiniz:

// Replace all new-line then id patterns with new-line 0+id
$line = preg_replace('/\n(\d)/',"\n0$1",$line);

// Split on new-line then id
$linevalues = preg_split("/\n\d/",$data);

İlk adım, bir sayısal değer ardından yeni bir satır tüm satırları tanımlar. Daha sonra, bu sayısal değere "0" slash konulur. İkinci satır, yeni bir satır sonra tamsayı bulmak nerede böler.

"0" preg_split sonraki maçlarda eşleşen karakter kaldırır gibi id önüne eklenir.

Dediğim gibi, bir satır sonlarını metin bir sayı ile yeni bir satır başlatmak değil emin iseniz, bu sadece çalışır.

Kullan fgetcsv ve sizin için bütün ilgilenirim. Kendi CSV ayrıştırıcı olması gereken bazı öncelikli nedeni yoksa.