Парсинг файла CSV с помощью простофили

Потратив один день на эту проблему, я наконец нашел решение.

Необходимо выполнить два шага:

1- При использовании OleDBConnection оказалось, что вы не можете прочитать исходный файл, поскольку, как только файл открывается, он начинает использовать загруженный файл. Это подталкивает нас к копированию файла в другое временное местоположение. Поэтому добавьте строку проверки в код.

FileUploadControl.SaveAs(filePath + fileName); //This is the line
OleDbConnection fileConnection = new OleDbConnection(FileConnectionString(filePath, fileName));
fileConnection.Open();

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

2- Во временной папке (папке) должен быть NETWORK SERVICE как пользователь. Перейдите в настройки папки -> Безопасность -> Добавить пользователя -> Добавить сетевой сервис с правами чтения и записи.

Тогда тебе будет хорошо идти. Спасибо @Bran и @techturtle за то, что вдохновили меня в комментариях.

12
задан Benjamin W. 16 August 2017 в 14:46
поделиться

5 ответов

Короткий ответ, "Я не использовал бы простофилю для парсинга CSV, если CSV содержит неловкие данные", где 'неловкий' вещи средств как запятые в данных поля CSV.

Следующий вопрос, "Что другую обработку Вы собирающийся делать", так как это будет влиять на то, какие альтернативы Вы используете.

Я, вероятно, использовал бы Perl и текст:: CSV или текст:: модули CSV_XS, чтобы читать и обработать данные. Помните, Perl был первоначально записан частично как awk и sed уничтожитель - следовательно a2p и s2p программы все еще распределили с Perl, которые преобразовывают awk и sed сценарии (соответственно) в Perl.

11
ответ дан 2 December 2019 в 04:34
поделиться

Если допустимый, я использовал бы Python csv модуль, обращая особое внимание на диалект используемые и требуемые параметры форматирования, для парсинга файла CSV, который Вы имеете.

4
ответ дан 2 December 2019 в 04:34
поделиться

Я не абсолютно уверен, является ли это правильным способом сделать вещи. Я работал бы над файлом CSV, в котором или все значения к заключенному в кавычки или ни одному. Btw, awk позволяет regexes быть Разделителями полей. Проверьте, полезно ли это.

1
ответ дан 2 December 2019 в 04:34
поделиться

csv2delim.awk

# csv2delim.awk converts comma delimited files with optional quotes to delim separated file
#     delim can be any character, defaults to tab
# assumes no repl characters in text, any delim in line converts to repl
#     repl can be any character, defaults to ~
# changes two consecutive quotes within quotes to '

# usage: gawk -f csv2delim.awk [-v delim=d] [-v repl=`"] input-file > output-file
#       -v delim    delimiter, defaults to tab
#       -v repl     replacement char, defaults to ~

# e.g. gawk -v delim=; -v repl=` -f csv2delim.awk test.csv > test.txt

# abe 2-28-7
# abe 8-8-8 1.0 fixed empty fields, added replacement option
# abe 8-27-8 1.1 used split
# abe 8-27-8 1.2 inline rpl and "" = '
# abe 8-27-8 1.3 revert to 1.0 as it is much faster, split most of the time
# abe 8-29-8 1.4 better message if delim present

BEGIN {
    if (delim == "") delim = "\t"
    if (repl == "") repl = "~"
    print "csv2delim.awk v.m 1.4 run at " strftime() > "/dev/stderr" ###########################################
}

{
    #if ($0 ~ repl) {
    #   print "Replacement character " repl " is on line " FNR ":" lineIn ";" > "/dev/stderr"
    #}
    if ($0 ~ delim) {
        print "Temp delimiter character " delim " is on line " FNR ":" lineIn ";" > "/dev/stderr"
        print "    replaced by " repl > "/dev/stderr"
    }
    gsub(delim, repl)

    $0 = gensub(/([^,])\"\"/, "\\1'", "g")
#   $0 = gensub(/\"\"([^,])/, "'\\1", "g")  # not needed above covers all cases

    out = ""
    #for (i = 1;  i <= length($0);  i++)
    n = length($0)
    for (i = 1;  i <= n;  i++)
        if ((ch = substr($0, i, 1)) == "\"")
            inString = (inString) ? 0 : 1 # toggle inString
        else
            out = out ((ch == "," && ! inString) ? delim : ch)
    print out
}

END {
    print NR " records processed from " FILENAME " at " strftime() > "/dev/stderr"
}

test.csv

"first","second","third"
"fir,st","second","third"
"first","sec""ond","third"
" first ",sec   ond,"third"
"first" , "second","th  ird"
"first","sec;ond","third"
"first","second","th;ird"
1,2,3
,2,3
1,2,
,2,
1,,2
1,"2",3
"1",2,"3"
"1",,"3"
1,"",3
"","",""
"","""aiyn","oh"""
"""","""",""""
11,2~2,3

test.bat

rem test csv2delim
rem default is: -v delim={tab} -v repl=~
gawk                      -f csv2delim.awk test.csv > test.txt
gawk -v delim=;           -f csv2delim.awk test.csv > testd.txt
gawk -v delim=; -v repl=` -f csv2delim.awk test.csv > testdr.txt
gawk            -v repl=` -f csv2delim.awk test.csv > testr.txt
2
ответ дан 2 December 2019 в 04:34
поделиться

Вот то, что я придумал. Любые комментарии и/или лучшие решения ценились бы.

BEGIN { FS="," }
{
  for (i=1; i<=NF; i++) {
    f[++n] = $i
    if (substr(f[n],1,1)=="\"") {
      while (substr(f[n], length(f[n]))!="\"" || substr(f[n], length(f[n])-1, 1)=="\\") {
        f[n] = sprintf("%s,%s", f[n], $(++i))
      }
    }
  }
  for (i=1; i<=n; i++) printf "field #%d: %s\n", i, f[i]
  print "----------------------------------\n"
}

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

0
ответ дан 2 December 2019 в 04:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: