Необходимо эффективно сканировать управляющие символы ascii нижнего уровня в больших файлах Excel - PullRequest
0 голосов
/ 06 мая 2020

Я работаю над процедурой проверки ETL для сканирования недопустимых символов ascii перед обработкой. В этом случае недопустимый определяется как символы ascii в диапазоне от 0 до 31.

В службе проверки C# ETL я использую OfficeOpen Xml для проверки содержимого файлов Excel.

Кто-нибудь знает более эффективный способ поиска по содержимому, кроме циклического поиска по каждому листу, каждому столбцу и каждой строке? Файлы могут быть очень большими, и проверка должна быть максимально быстрой.

Есть ли доступ к необработанному буферу xml? Было бы быстрее распаковать файлы xml и сканировать их содержимое?

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Я написал тестовую программу и придумал 14 вариантов с использованием string [] и List для структур данных и следующих итераторов:

1:
foreach (char c in s.ToCharArray())

2:

byte[] ASCIIValues = Encoding.ASCII.GetBytes(s);
foreach (byte code in ASCIIValues)

3:

Regex rx = new Regex(@"/[^ -~]/", RegexOptions.Compiled | RegexOptions.IgnoreCase);
MatchCollection matches = rx.Matches(s);

4:

for(int x=0; x < s.Length; x++)
  • Менее 100 000 элементов с итерацией foreach по строке [] с использованием метода 2 самое быстрое среднее время.
  • Более 100 000 элементов, использующих Parallel.ForEach в строке [] с использованием метода 2, в среднем дает самый быстрый результат.
  • Более 1 000 000 элементов с использованием Parallel.ForEach в строке [] с использованием метода 1 в среднем самый быстрый.
  • Менее 10 000 элементов с использованием Parallel.ForEach в строке [] или List <> с использованием всех методов было самым медленным.
  • При отсутствии параллелизма 1 обогнал 2 как самый быстрый из количество переданных элементов 500000 (??)
  • Регулярное выражение всегда было медленнее по сравнению с итерацией символов или байтов
  • Для чего-то около 100000 a foreach l oop с использованием string [] и метода 2 был самым быстрым
0 голосов
/ 06 мая 2020

Во-первых, я думаю, что пришло время для Speed ​​Rant: https://ericlippert.com/2012/12/17/performance-rant/

Вопрос в том, где именно сейчас находится узкое место. Мой instict говорит мне, что это должен быть диск. Вы работаете с файлами, обычно это Диск. В этом случае, если не считать загрузки каждой ячейки в память только один раз, ускорить особо нечего.

Однако вы выполняете довольно глубокую обработку строк, так как вам придется go через каждый символ. Так что на это может быть потрачено релевантных времени. Скорее всего, это не узкое место, а то, что вы можете отрицать как стоимость.

Возможно, вы сможете выполнить некоторую асинхронизацию, имея следующую загрузку ячейки / строки в фоновом режиме, пока вы обрабатываете эту. Такой подход, как Directory.EnumerateFiles() vs Directory.GetFiles, может работать: https://docs.microsoft.com/en-us/dotnet/api/system.io.directory.enumeratefiles

Row, похоже, имеет функцию GetEnumerator . Но это может быть просто для получения перечислителя для кода, который требует перечислителей и фактически не включает отложенную / фоновую загрузку (например, как перечислитель, неявно созданный для циклов foreach).

...