require_once ($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/csv_data.php";);
$csvFile = new CCSVData('R', true);
$csvFile->LoadFile($_FILES['csv']['tmp_name']);
$csvFile->SetDelimiter(',');
while ($arRes = $csvFile->Fetch()) {
ec($arRes);
}
Собственно: - подключаем файл класса работы с CSV - создаем объект класса, указываем, что будет использоваться разделитель (R, есть еще фикс.поля F), и первая строка содержит заголовки (true); можно не указывать эти параметры и задать отдельными методами
- загружаем файл - ставим делиметер, где допустимые параметры: \t (табуляция), запятая, пробел, точка с запятой. - бежим как при обычной выборке из базы (напомню, Fetch возвращает НЕ обработанные данные, а GetNext безопасные).
Коллеги подскажите, а есть ли какой-то изящный выход, когда клиент подсовывает файлы cp1251 на импорт на сайт в utf-8 Понятно, что битрикс отправляет клиента перекодировать файл вручную. Есть функции перекодирования строк, но не валиться ли импорт при этом на ощутимом кол-ве данных? Кто-то решал эту дилемму ?
А как парсер поведёт себя, когда встретит недопустимые символы? Если файл в кодировке cp1251, а сайт в UTF8, то при парсинге могут появится невалидные юникод-последовательности. Поэтому нужно сначала конвертировать строковые данные, а потом уже парсить. С другой стороны, читать построчно тоже нельзя, потому что перевод строки может встретиться в экранированном виде (в кавычках), и функция построчного чтения неправильно прочтёт такую строку. Получается, прежде чем парсить, нужно конвертировать кодировку, а чтобы считать одну строку, нужно распарсить. Выходит, чтобы считать одну строку, нужно сначала перекодировать весь файл, а уж потом его парсить.
Тут я ошибся. На момент написания того коммента я не знал следующего: все символы, которые обычно используются в качестве разделителей в CSV: запятая, точка с запятой, двойные кавычки, горизонтальная табуляция — кодируются в UTF-8 точно так же, как и в CP1251, поскольку принадлежат ASCII, а вся ASCII в обеих этих кодировках кодируется одинаково.
Если бы парсер пытался каким-то образом интерпретировать другие символы в потоке ввода, помимо символов разделителей, которые ему нужно распарсить, то ошибка была бы следующая. Допустим, у Вас в файле всего два байта: ГL -- кириллическая Г, потом латинская L. Последовательность 1100 0011 (Г), 0100 1100 (L) является недопустимой в UTF-8, т. к. после 11xx xxxx должна всегда следовать 10xx xxxx.
Но, как я предполагаю (не проверял), битриксовый парсер CSV не интерпретирует никакие байты входящего потока, кроме тех, которые ему нужны для разделения строк и ячеек. Поэтому конкретно для сайта на UTF-8 и файла в CP1251 ошибки быть не должно, по идее.
Но такой алгоритм, несомненно, содержит в себе принципиальную, идеологическую ошибку, т. к. не для любых двух кодировок это верно. В частности, если бы сайт был на другой Unicode-кодировке, напр., UTF-16, (не поддерживается в Битрикс) то упомянутая мной проблема непременно могла бы иметь место при определённой последовательности входных символов CP1251 — поскольку в символы-разделители CSV в CP1251 представлены однобайтовыми последовательностями, а в UTF-16 — двухбайтовыми.
TLDR, это, по идее, рабочий лайфхак, который подходит не для любых кодировок.
Semenov Roman, да никто же не спорит Тут вопрос скорее не "почему не использовали именно эту фичу", а "зачем понадобилось писать прослойку, да еще и не очень удобную"
Эту фичу наверное нужно использовать для того что бы избежать всяческих проблем с кодировкой и прочими настройками которые Битрикс учитывает. Антон там в строке подключения библиортеки лишнее
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».