Регистрация  |  Вход

А как Вы парсите *SV?

Здравствуйте!

Столкнулся с проблемой, есть *SV файл, как его красиво распарсить,

Например CSV файл:

First Name,Second Name,Description\n

Test,Test,"123,some text\nand some text"\n

У меня только идея, чтобы сначала отдельно обработать header. Потом заменить все <""> на какуето текстовую константу(так как excel например <"> удваивает, те что были изначально в ячейке), чтобы потом обратно вернуть, а потом искать что раньше <,> или <">(после замени всех <""> в тексте остались только <"> добавлены excel'ем) или <'\n'>,

если это <,> или <'\n'>, то вырезаем нужную часть, до этих символов, если же <"> то ищем вторую <"> и тоже вырезаем. Такой подход мне кажется, не есть эффективным.

Пробовал написать регулярку, но получилось несколько строк абсолютно не читаемого и нерабочего текста.

Подскажите, а как Вы парсите *SV файлы?

И как можно решить проблему того, что в разных системах, разные окончание строк, например в Unix это '\n', в Mac OS это '\r', а в Windows это '\r\n'.

Изначально, я делал String.split('(\r\n|\n|\r)'), но такой вариант разбивки на строки не подходить, когда в значении ячейки есть переноси строк.

Здравствуйте!
Столкнулся с проблемой, есть *SV файл, как его красиво распарсить, 

Например CSV файл:
First Name,Second Name,Description\n
Test,Test,"123[b][i],[/i][/b]some text[b][u]\n[/u][/b]and some text"\n

У меня только идея, чтобы сначала отдельно обработать header. Потом заменить все <""> на какуето текстовую константу(так как excel например <"> удваивает, те что были изначально в ячейке), чтобы потом обратно вернуть,  а потом искать что раньше <,> или <">(после замени всех <""> в тексте остались только <"> добавлены excel'ем) или <'\n'>,
если это <,> или <'\n'>, то вырезаем нужную часть, до этих символов,  если же <"> то ищем вторую <"> и тоже вырезаем. Такой подход мне кажется, не есть эффективным. 

Пробовал написать регулярку, но получилось несколько строк абсолютно не читаемого и нерабочего текста.

Подскажите, а как Вы парсите *SV файлы?

И как можно решить проблему того, что в разных системах, разные окончание строк, например в Unix это '\n', в Mac OS это '\r', а в Windows это '\r\n'.

Изначально, я делал String.split('(\r\n|\n|\r)'), но такой вариант разбивки на строки не подходить, когда в значении ячейки есть переноси строк.

talex
Здравствуйте!
Столкнулся с проблемой, есть *SV файл, как его красиво распарсить,

Например CSV файл:
First Name,Second Name,Description\n
Test,Test,"123,some text\nand some text"\n

У меня только идея, чтобы сначала отдельно обработать header. Потом заменить все <""> на какуето текстовую константу(так как excel например <"> удваивает, те что были изначально в ячейке), чтобы потом обратно вернуть, а потом искать что раньше <,> или <">(после замени всех <""> в тексте остались только <"> добавлены excel'ем) или <'\n'>,
если это <,> или <'\n'>, то вырезаем нужную часть, до этих символов, если же <"> то ищем вторую <"> и тоже вырезаем. Такой подход мне кажется, не есть эффективным.

Пробовал написать регулярку, но получилось несколько строк абсолютно не читаемого и нерабочего текста.

Подскажите, а как Вы парсите *SV файлы?

И как можно решить проблему того, что в разных системах, разные окончание строк, например в Unix это '\n', в Mac OS это '\r', а в Windows это '\r\n'.

Изначально, я делал String.split('(\r\n|\n|\r)'), но такой вариант разбивки на строки не подходить, когда в значении ячейки есть переноси строк.


Ребят, честное слово. Иногда складывается такое ощущение что вы работаете без интернета.

https://www.google.co.il/webhp?sourceid=chrome-instant&rlz=2C1PRFC_enIL0536IL0536&ion=1&espv=2&ie=UTF-8#q=salesforce%20parse%20csv

а точнее https://developer.salesforce.com/page/Code_Samples

[quote="talex"]Здравствуйте!
Столкнулся с проблемой, есть *SV файл, как его красиво распарсить, 

Например CSV файл:
First Name,Second Name,Description\n
Test,Test,"123[b][i],[/i][/b]some text[b][u]\n[/u][/b]and some text"\n

У меня только идея, чтобы сначала отдельно обработать header. Потом заменить все <""> на какуето текстовую константу(так как excel например <"> удваивает, те что были изначально в ячейке), чтобы потом обратно вернуть,  а потом искать что раньше <,> или <">(после замени всех <""> в тексте остались только <"> добавлены excel'ем) или <'\n'>,
если это <,> или <'\n'>, то вырезаем нужную часть, до этих символов,  если же <"> то ищем вторую <"> и тоже вырезаем. Такой подход мне кажется, не есть эффективным. 

Пробовал написать регулярку, но получилось несколько строк абсолютно не читаемого и нерабочего текста.

Подскажите, а как Вы парсите *SV файлы?

И как можно решить проблему того, что в разных системах, разные окончание строк, например в Unix это '\n', в Mac OS это '\r', а в Windows это '\r\n'.

Изначально, я делал String.split('(\r\n|\n|\r)'), но такой вариант разбивки на строки не подходить, когда в значении ячейки есть переноси строк.[/quote]


Ребят, честное слово. Иногда складывается такое ощущение что вы работаете без интернета.

[url]https://www.google.co.il/webhp?sourceid=chrome-instant&rlz=2C1PRFC_enIL0536IL0536&ion=1&espv=2&ie=UTF-8#q=salesforce%20parse%20csv[/url]

а точнее [url]https://developer.salesforce.com/page/Code_Samples[/url]

Wilder, ну чего ты так строго?
А вообще в данную тему - буквально недавно читал где-то на reddit умную мысль - "не надо изобретать то что уже изобретено и работает". Писать CSV парсер с нуля это неблагодарное занятие, что Alex нам с удовольствием продемонстрировал. Боюсь даже предположить сколько там может быть частных случаев, которые надо правильно обработать. А в мире уже столько профессиональных библиотек, которые написаны и испытаны целыми сообществами профессионалов.

Так что если готового решения в SF нет (хотя оно должно быть), то лучше воспользоваться библиотеками на других языках. Поднять свой внешний сервис, скармливать ему CSV, а он чтобы возвращал "правильные" данные (JSON например или сразу обрабатывал, чтобы не нагружать SF c его лимитами). Вот это понимаю качественный код.

Это касается не только CSV. На форуме уже не раз поднимались вопросы разбора различных форматов.

Wilder, ну чего ты так строго? :)

А вообще в данную тему - буквально недавно читал где-то на reddit умную мысль - "не надо изобретать то что уже изобретено и работает". Писать CSV парсер с нуля это неблагодарное занятие, что Alex нам с удовольствием продемонстрировал. Боюсь даже предположить сколько там может быть частных случаев, которые надо правильно обработать. А в мире уже столько профессиональных библиотек, которые написаны и испытаны целыми сообществами профессионалов. 

Так что если готового решения в SF нет (хотя оно должно быть), то лучше воспользоваться библиотеками на других языках. Поднять свой внешний сервис, скармливать ему CSV, а он чтобы возвращал "правильные" данные (JSON например или сразу обрабатывал, чтобы не нагружать SF c его лимитами). Вот это понимаю качественный код. 

Это касается не только CSV. На форуме уже не раз поднимались вопросы разбора различных форматов.

Dmitry Shnyrev
Wilder, ну чего ты так строго?
А вообще в данную тему - буквально недавно читал где-то на reddit умную мысль - "не надо изобретать то что уже изобретено и работает". Писать CSV парсер с нуля это неблагодарное занятие, что Alex нам с удовольствием продемонстрировал. Боюсь даже предположить сколько там может быть частных случаев, которые надо правильно обработать. А в мире уже столько профессиональных библиотек, которые написаны и испытаны целыми сообществами профессионалов.

Так что если готового решения в SF нет (хотя оно должно быть), то лучше воспользоваться библиотеками на других языках. Поднять свой внешний сервис, скармливать ему CSV, а он чтобы возвращал "правильные" данные (JSON например или сразу обрабатывал, чтобы не нагружать SF c его лимитами). Вот это понимаю качественный код.

Это касается не только CSV. На форуме уже не раз поднимались вопросы разбора различных форматов.

Вообще стараюсь использовать XML вместо CSV.

[quote="Dmitry Shnyrev"]Wilder, ну чего ты так строго? :)

А вообще в данную тему - буквально недавно читал где-то на reddit умную мысль - "не надо изобретать то что уже изобретено и работает". Писать CSV парсер с нуля это неблагодарное занятие, что Alex нам с удовольствием продемонстрировал. Боюсь даже предположить сколько там может быть частных случаев, которые надо правильно обработать. А в мире уже столько профессиональных библиотек, которые написаны и испытаны целыми сообществами профессионалов. 

Так что если готового решения в SF нет (хотя оно должно быть), то лучше воспользоваться библиотеками на других языках. Поднять свой внешний сервис, скармливать ему CSV, а он чтобы возвращал "правильные" данные (JSON например или сразу обрабатывал, чтобы не нагружать SF c его лимитами). Вот это понимаю качественный код. 

Это касается не только CSV. На форуме уже не раз поднимались вопросы разбора различных форматов.[/quote]

Вообще стараюсь использовать XML вместо CSV.

Ребят, честное слово. Иногда складывается такое ощущение что вы работаете без интернета.

Вы зайдите на форумы developer.salesforce.com... Вот там такое ощущение практически константно :D

[quote]Ребят, честное слово. Иногда складывается такое ощущение что вы работаете без интернета.[/quote]

Вы зайдите на форумы developer.salesforce.com... Вот там такое ощущение практически константно  :D

Если бы было мое желание я очень много перенес из SF на внешние сервисы, а SF юзал бы как головной мозг. Ибо apex уступает возможностям больших языков(хотя и чертовски удобный и простой).
А вот заказчику хер докажешь что нужен сторонний сервис... Вот к примеру доделывал я сайт на SF, и беда была с хранением файлов и картинок.(

Если бы было мое желание я очень много перенес из SF  на внешние сервисы, а SF юзал бы как головной мозг. Ибо apex уступает возможностям больших языков(хотя и чертовски удобный и простой).
А вот заказчику хер докажешь что нужен сторонний сервис...  Вот к примеру доделывал я сайт на SF, и беда была с хранением файлов и картинок.(

AkiraDio
Если бы было мое желание я очень много перенес из SF на внешние сервисы, а SF юзал бы как головной мозг. Ибо apex уступает возможностям больших языков(хотя и чертовски удобный и простой).
А вот заказчику хер докажешь что нужен сторонний сервис... Вот к примеру доделывал я сайт на SF, и беда была с хранением файлов и картинок.(

Поддерживаю, Виктор. Очень много задач просятся чтобы их вынесли из SF в виду строгих лимитов на выполнение кода. По мне, так просто сплю и вижу что Salesforce когда-нибудь сильнее привяжут к Heroku (который, блин, они купили наверное не просто так) и вся сложная логика, и вообще весь код уйдет на эту платформу. Хотя с точки зрения "содрать бабла" это невыгодно для SF.

[quote="AkiraDio"]Если бы было мое желание я очень много перенес из SF  на внешние сервисы, а SF юзал бы как головной мозг. Ибо apex уступает возможностям больших языков(хотя и чертовски удобный и простой).
А вот заказчику хер докажешь что нужен сторонний сервис...  Вот к примеру доделывал я сайт на SF, и беда была с хранением файлов и картинок.([/quote]
Поддерживаю, Виктор. Очень много задач просятся чтобы их вынесли из SF в виду строгих лимитов на выполнение кода. По мне, так просто сплю и вижу что Salesforce когда-нибудь сильнее привяжут к Heroku (который, блин, они купили наверное не просто так) и вся сложная логика, и вообще весь код уйдет на эту платформу. Хотя с точки зрения "содрать бабла" это невыгодно для SF.

talex
Подскажите, а как Вы парсите *SV файлы?

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

но с этого все веселье только начинается.
файлы более 2м падают при попытке распилить их с помощью стрингового метода split('\r\n'); с сообщением что regex слишком сложен.
решение быстро нашлось в поиске - спец класс, который пилит csv на строки не разом, а по кусочку, и лимиты в порядке.

а далее борьба с содержание файла - что если значение в поле заканчтвается на "," и прочее.
в общем - это морока, но разобраться стоит.

[quote="talex"]
Подскажите, а как Вы парсите *SV файлы?
[/quote]

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

но с этого все веселье только начинается.
файлы более 2м падают при попытке распилить их с помощью стрингового метода split('\r\n'); с сообщением что regex слишком сложен. 
решение быстро нашлось в поиске - спец класс, который пилит csv на строки не разом, а по кусочку, и лимиты в порядке.

а далее борьба с содержание  файла - что если значение в поле заканчтвается на "," и прочее.
 в общем - это морока, но разобраться стоит.

"не надо изобретать то что уже изобретено и работает"

Решил послушаться совета.

Все то что

я с первого поискового запроса нашел
либо не может распарсить нормально файл, либо валиться по лимитам, пытаться подкоректировать их, это гиблое дело, с CSV и подобными форматами (TSV, SCSV, и т.д.) очень много разных нюансов. И самое страшное что разделителями в CSV могут быть табы, запятие, точка с запятой..., но с этим уже ничего поделать нельзя, нужно еще й список разделителей видавать пользовалетелю.

Вообщем удалось найти js библиотеку, которая более менее справилась из поставленной задачей(но все равно проблемы есть, но с ними можно уже смирится).

[quote]"не надо изобретать то что уже изобретено и работает"[/quote]
Решил послушаться совета. 

Все то что [quote]я с первого поискового запроса нашел[/quote] либо не может распарсить нормально файл, либо валиться по лимитам, пытаться подкоректировать их, это гиблое дело, с CSV и подобными форматами (TSV, SCSV, и т.д.) очень много разных нюансов.  И самое страшное что разделителями в CSV могут быть табы, запятие, точка с запятой..., но с этим уже ничего поделать нельзя, нужно еще й список разделителей видавать пользовалетелю. 

Вообщем удалось найти js библиотеку, которая более менее справилась из поставленной задачей(но все равно проблемы есть, но с ними можно уже смирится).

talex
либо не может распарсить нормально файл, либо валиться по лимитам, пытаться подкоректировать их, это гиблое дело, с CSV и подобными форматами (TSV, SCSV, и т.д.) очень много разных нюансов.

да так и есть.

у меня CSV приходят с одного источника, всегда в одном формате, поэтому я настроил и пока работает.

но если найдешь какое то более универсальное и гибкое решение - выкладывай сюда - это полезная тема

[quote="talex"]либо не может распарсить нормально файл, либо валиться по лимитам, пытаться подкоректировать их, это гиблое дело, с CSV и подобными форматами (TSV, SCSV, и т.д.) очень много разных нюансов. [/quote]

да так и есть.

у меня CSV приходят с одного источника, всегда в одном формате, поэтому я настроил и пока работает.

но если найдешь какое то более универсальное и гибкое решение - выкладывай сюда - это полезная тема

продолжу больную и актуальную тему.

если в CSV файле в качестве разделителя текста указаны двойные кавычки - то значение после конвертации из CSV стринга в List<List<String>> allFieldsHere приходят с кавычками в начале и конце.

Ну ладно, удалим все кавычки вот так:

for(List<String> oneline : allFieldsHere){

for(String val :oneline){

val = val.replace('"', '');

}
}

и это не работает. А сам .replace('"', '') метод работает (вне данного примера). Глупо, но не пойму почему.
----
Еще заметил в чужом коде такой ход работы Email Service (Сервис получает мейл и работает с аттачментом):
- на сервисе включена опция "Convert Text Attachments to Binary Attachments".
- и в коде делается следующее: csvString = email.binaryAttachments[i].body.toString(). То есть выполняется обратная операция.

Вопрос: в такой организации работы с аттачментами (конвертировать в Binary и обратно) есть какой-то практический смысл (безопасность?) или его нет?

спасибо

продолжу больную и актуальную тему.

если в CSV файле в качестве разделителя текста указаны двойные кавычки - то значение после конвертации из CSV  стринга в [i]List<List<String>> allFieldsHere[/i] приходят с кавычками в начале и конце.

Ну ладно, удалим все кавычки вот так:
[i]
for(List<String> oneline : allFieldsHere){

                        for(String val :oneline){ 
			  	
			  	val = val.replace('"', '');

                             }
                    }[/i]

и это не работает. А сам [i].replace('"', '')[/i] метод работает (вне данного примера). Глупо, но не пойму почему.
----
Еще заметил в чужом коде такой ход работы Email Service (Сервис получает мейл и работает с аттачментом):
- на сервисе включена опция "Convert Text Attachments to Binary Attachments".
- и в коде делается следующее: csvString = email.binaryAttachments[i].body.toString(). То есть выполняется обратная операция.

Вопрос: в такой организации работы с аттачментами (конвертировать в Binary и обратно) есть какой-то практический смысл (безопасность?) или его нет?

спасибо
   

Разбор CSV и преобразование его значений в нужные типы - это целая тема.

Перечислю проблемы с которыми столкнулся:

а. проблемы с неправильной разбивкой на строки и\или значения.

б. проблемы с форматом файла: допустить что колонки будут всегда идти в одном порядке (line[2]) или искать нужную колонку (ее индекс)каждый раз по заглавию (но при этом допустить что заглавия не меняются).

в. проблемы с отсутствием значения в требуемых полях, невозможностью их преобразования или значение не попадает под список допустимых вариантов - здесь нужно каждый случай обрабатывать: останавливать код - оправлять письмо с описанием проблемы.

г. проблемы с аккуратностью заполнения таблицы - есть пропущенные строки, в последних строках - обрывочные данные.

добавляйте свои варианты

Разбор CSV и преобразование его значений в нужные типы - это целая тема.

Перечислю проблемы с которыми столкнулся:

а. проблемы с неправильной разбивкой на строки и\или значения.

б. проблемы с форматом файла: допустить что колонки будут всегда идти в одном порядке (line[2]) или искать нужную колонку (ее индекс)каждый раз по заглавию (но при этом допустить что заглавия не меняются).

в. проблемы с отсутствием значения в требуемых полях, невозможностью их преобразования или значение не попадает под список допустимых вариантов - здесь нужно каждый случай обрабатывать: останавливать код - оправлять письмо с описанием проблемы.

г. проблемы с аккуратностью заполнения таблицы - есть пропущенные строки, в последних строках - обрывочные данные.

добавляйте свои варианты

Сидел, думал о проблемах парсинга CSV, который требует определенных делимитеров и переводчика строк, и все равно ломается, если например значение в поле начинается с запятой или двойных кавычек (если они также используется в качестве текстового делимитера), и вспомнил слова:

wilder
Вообще стараюсь использовать XML вместо CSV.

а что из Excel (или программы-аналога) можно сохранить таблицу в виде xml файла?!

да можно.

и похоже на то, что разбор этого xml по <Row> and <Cell> избавит ото всех проблем с парсингом. Надо бы попробовать.

Сидел, думал о проблемах парсинга CSV, который требует определенных делимитеров и переводчика строк, и все равно ломается, если например значение в поле начинается с запятой или двойных кавычек (если они также используется в качестве текстового делимитера), и вспомнил слова:

[quote="wilder"]
Вообще стараюсь использовать XML вместо CSV.
[/quote]

а что из Excel (или программы-аналога) можно сохранить таблицу в виде xml  файла?!

да можно.

и похоже на то, что разбор этого xml по <Row> and <Cell> избавит ото всех проблем с парсингом. Надо бы попробовать.

По поводу XML парсера проблем нет, вот отличное рекурсивное решение. Просто не всегда есть возможность использовать XML вместо CSV. Например, callout response имеет только CSV допустимый формат, или заказчик требует использовать именно CSV.

По поводу XML парсера проблем нет, вот [url=http://developer.force.com/cookbook/recipe/parsing-xml-using-the-apex-dom-parser]отличное рекурсивное решение[/url]. Просто не всегда есть возможность использовать XML вместо CSV. Например, callout response имеет только CSV допустимый формат, или заказчик требует использовать именно CSV.