Замена или удаление новой строки чем-то другим, но только между одинарными или двойными кавычками с использованием PHP в файле CSV

У меня есть файл CSV, содержащий около 200 000 - 300 000 записей. Большинство записей можно разделить и вставить в базу данных MySQL с помощью простого

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

а затем значения, разделенные

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

а затем вставляется в базу данных с использованием правильного типа данных, то есть int, float, string, text и т. д.

Однако в некоторых записях есть текстовый столбец, в строке которого есть \ n. Что ломается при использовании $ line = explode ("\ n", $ fileData); метод. Каждая строка данных, которую необходимо вставить в базу данных, содержит примерно 216 столбцов. не в каждой строке есть запись с \ n в строке. Однако каждый раз, когда в строке встречается \ n, он заключен в пару одинарных кавычек (')

каждая строка настроена в следующем формате:

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

пример:

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

Как видно из примера, большинство записей можно легко разделить с помощью методов, показанных выше. Это вторая запись в примере, которая вызывает проблему.

Новые строки - это только \ n, и файл вообще не включает \ r в файл.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
1 224
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Если вы можете быть уверены, что каждая новая строка, начинающаяся с числа, является допустимой новой строкой (то есть не в середине текстового описания), вы можете попробовать что-то вроде следующего:

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

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

Первый шаг идентифицирует все строки, у которых есть новая строка, за которой следует числовое значение. Затем к этому числовому значению добавляется «0». Вторая строка разделяется там, где сначала появляется новая строка, а затем целое число.

«0» добавляется перед идентификатором, поскольку preg_split удаляет совпадающие символы из последующих совпадений.

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

Ответ принят как подходящий

Если данные csv находятся в файле, вы можете просто использовать fgetcsv (), как указывали другие. fgetcsv правильно обрабатывает встроенные символы новой строки.

Однако, если ваши данные csv находятся в строке (например, $ fileData в вашем примере), следующий метод может быть полезен, поскольку str_getcsv () работает только с строкой за раз и не может разбить весь файл на записи.

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

Как только у вас будет полная запись, разделите ее на кавычки (снова используя explode ()). Поля с нечетными номерами заключаются в кавычки (таким образом, встроенные запятые не являются специальными), а поля с четными номерами - нет.

Пример:

# 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;
}

как насчет ручного перебора данных от начала до конца с одним или двумя циклами for? Он медленнее, чем explode(), но по котировкам легче получить последовательные и надежные результаты.

Если вы выберете этот метод, не забудьте принять во внимание экранированные кавычки.

Другой совет здесь, конечно, действителен, особенно если вы хотите написать свой собственный анализатор CSV, однако, если вы просто хотите получить данные, используйте функцию fgetcsv () и не беспокойтесь о деталях реализации.

Используйте fgetcsv, и он позаботится обо всем за вас. Если нет какой-либо основной причины, вам нужен собственный парсер CSV.

Я не знаком с функцией fgetcsv (). Это первый раз, когда мне было поручено взять около 300 МБ файлов csv и вставить их в базу данных MySQL. Первые несколько файлов были легкими, поскольку в них не было встроенных новых строк.

Jayrox 09.10.2008 17:49

Другие вопросы по теме