класс CSV
Этот класс предоставляет полный интерфейс к файлам и данным в формате CSV. Он предлагает инструменты для чтения и записи из строк или объектов IO, по мере необходимости.
Наиболее общий интерфейс библиотеки:
csv = CSV.new(string_or_io, **options) # Reading: IO object should be open for read csv.read # => array of rows # or csv.each do |row| # ... end # or row = csv.shift # Writing: IO object should be open for write csv << row
Существует несколько специализированных методов класса для однострочного чтения или записи, описанных в разделе Специализированные методы.
Если в ::new передаётся строка String, она внутренне оборачивается в объект StringIO.
options может использоваться для указания конкретного формата CSV (разделители столбцов, разделители строк, кавычки значений и так далее), а также для преобразования данных. Подробное описание последнего см. в разделе Преобразование.
Специализированные методы
Чтение
# From a file: all at once
arr_of_rows = CSV.read("path/to/file.csv", **options)
# iterator-style:
CSV.foreach("path/to/file.csv", **options) do |row|
# ...
end
# From a string
arr_of_rows = CSV.parse("CSV,data,String", **options)
# or
CSV.parse("CSV,data,String", **options) do |row|
# ...
end
Запись
# To a file
CSV.open("path/to/file.csv", "wb") do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
# To a String
csv_string = CSV.generate do |csv|
csv << ["row", "of", "CSV", "data"]
csv << ["another", "row"]
# ...
end
Сокращения
# Core extensions for converting one line
csv_string = ["CSV", "data"].to_csv # to CSV
csv_array = "CSV,String".parse_csv # from CSV
# CSV() method
CSV { |csv_out| csv_out << %w{my data here} } # to $stdout
CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin
Преобразование
CSV с заголовками
CSV позволяет указать имена столбцов файла CSV, находятся ли они в данных или предоставляются отдельно. Если заголовки указаны, методы чтения возвращают экземпляр CSV::Table, состоящий из CSV::Row.
# Headers are part of data
data = CSV.parse(<<~ROWS, headers: true)
Name,Department,Salary
Bob,Engineering,1000
Jane,Sales,2000
John,Management,5000
ROWS
data.class #=> CSV::Table
data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000">
data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
# Headers provided by developer
data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
Чтение типизированных данных
CSV позволяет предоставить набор преобразователей данных, например, преобразований для применения к входным данным. Преобразователь может быть символом из ключей константы CSV::Converters или лямбдой.
# Without any converters:
CSV.parse('Bob,2018-03-01,100')
#=> [["Bob", "2018-03-01", "100"]]
# With built-in converters:
CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date])
#=> [["Bob", #<Date: 2018-03-01>, 100]]
# With custom converters:
CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }])
#=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]]
CSV и кодировки символов (M17n или многоязычность)
Этот новый парсер CSV поддерживает многоязычие. Парсер работает в кодировке Encoding объекта IO или String, из которого или в который производится чтение или запись. Ваши данные никогда не транскодируются (если вы не попросите Ruby их транскодировать), и они будут анализироваться непосредственно в кодировке Encoding. Таким образом, CSV вернёт массивы или строки строк в кодировке Encoding ваших данных. Это достигается путём транскодирования самого парсера в вашу кодировку Encoding.
Некоторое транскодирование должно происходить, конечно, для поддержки этой многокодированной поддержки. Например, :col_sep, :row_sep, и :quote_char должны быть транскодированы для соответствия вашим данным. Надеюсь, это делает весь процесс прозрачным, так как значения по умолчанию CSV просто магически работают с вашими данными. Однако, вы можете вручную установить эти значения в целевой кодировке Encoding, чтобы избежать трансляции.
Также важно отметить, что, хотя весь основной парсер CSV теперь не зависит от Encoding, некоторые функции не зависят от него. Например, встроенные преобразователи попытаются транскодировать данные в UTF-8 перед преобразованием. Снова, вы можете предоставить пользовательские преобразователи, которые осознают ваши кодировки, чтобы избежать этой трансляции. Для меня слишком сложно поддерживать родственные преобразования во всех кодировках Ruby.
В любом случае, практическая сторона этого проста: убедитесь, что объекты IO и String, переданные в CSV, имеют установленную соответствующую кодировку Encoding, и всё должно работать. Методы CSV, которые позволяют открывать объекты IO (CSV::foreach(), CSV::open(), CSV::read() и CSV::readlines()), позволяют указать кодировку Encoding.
Одно небольшое исключение возникает при генерации CSV в строку String с кодировкой Encoding, которая не совместима с ASCII. Для CSV нет существующих данных, которые можно использовать для подготовки, и, следовательно, вам, вероятно, придётся вручную указать желаемую кодировку Encoding в большинстве таких случаев. Он будет пытаться угадать, используя поля в строке вывода, когда используется CSV::generate_line() или Array#to_csv().
Я постараюсь указать любые другие проблемы с Encoding в документации методов по мере их возникновения.
Это было протестировано по мере возможности со всеми кодировками, кроме «фиктивных», которые поставляются с Ruby. Однако это новый, смелый код, и в нём могут быть ошибки. Пожалуйста, не стесняйтесь сообщить о любых найденных проблемах.
Константы
- ConverterEncoding
-
Кодировка, используемая всеми преобразователями.
- Converters
-
Этот
Hashсодержит встроенные преобразователиCSV, к которым можно получить доступ по имени. Вы можете выбратьConvertersс помощьюCSV.convert()или черезoptionsHash, переданный вCSV::new().-
:integer -
Преобразует любой тип поля, который принимает Integer().
-
:float -
Преобразует любое поле, которое принимает Float().
-
:numeric -
Комбинация
:integerи:float. -
:date -
Преобразует любое поле, которое принимает
Date::parse(). -
:date_time -
Преобразует любое поле, которое принимает
DateTime::parse(). -
:all -
Все встроенные преобразователи. Комбинация
:date_timeи:numeric.
Все встроенные преобразователи преобразуют данные поля в UTF-8 перед выполнением преобразования. Если данные не могут быть преобразованы в UTF-8, преобразование завершится ошибкой, и поле останется неизменным.
Этот
Hashнамеренно не заморожен, и пользователи могут добавлять в него значения, к которым могут получить доступ все объектыCSV.Для добавления комбинированного поля значение должно быть массивом
Arrayимён. Комбинированные поля могут быть вложены друг в друга. -
- DEFAULT_OPTIONS
-
Параметры, используемые, когда вызывающий код не предоставляет альтернатив. Они включают:
-
:col_sep -
"," -
:row_sep -
:auto -
:quote_char -
'"' -
:field_size_limit -
nil -
:converters -
nil -
:unconverted_fields -
nil -
:headers -
false -
:return_headers -
false -
:header_converters -
nil -
:skip_blanks -
false -
:force_quotes -
false -
:skip_lines -
nil -
:liberal_parsing -
false -
:quote_empty -
true
-
- DateMatcher
-
Регулярное выражение, используемое для поиска и преобразования некоторых распространённых форматов
Date. - DateTimeMatcher
-
Регулярное выражение, используемое для поиска и преобразования некоторых распространённых форматов
DateTime. - FieldInfo
-
Структура
FieldInfoсодержит информацию о позиции поля в источнике данных, из которого оно было считано.CSVпередаст эту структуруStructнекоторым блокам, принимающим решения на основе структуры поля. См.CSV.convert_fields()для примера.-
index -
Индекс поля в строке (нумерация с нуля).
-
line -
Строка источника данных, из которой взята эта строка.
-
header -
Заголовок столбца, если он доступен.
-
- HeaderConverters
-
Этот
Hashсодержит встроенные преобразователи заголовковCSV, к которым можно получить доступ по имени. Вы можете выбратьHeaderConvertersс помощьюCSV.header_convert()или черезoptionsHash, переданный вCSV::new().-
:downcase -
Вызывает downcase() для заголовка
String. -
:symbol -
Удаляются ведущие/заключительные пробелы, строка переводится в нижний регистр, оставшиеся пробелы заменяются на нижние подчеркивания, небуквенно-цифровые символы удаляются, и, наконец, вызывается to_sym().
Все встроенные преобразователи заголовков преобразуют данные заголовков в UTF-8 перед выполнением преобразования. Если данные не могут быть преобразованы в UTF-8, преобразование завершится ошибкой, и заголовок останется неизменным.
Этот
Hashнамеренно не заморожен, и пользователи могут добавлять в него значения, к которым могут получить доступ все объектыCSV.Для добавления комбинированного поля значение должно быть массивом
Arrayимён. Комбинированные поля могут быть вложены друг в друга. -
- VERSION
-
Версия установленной библиотеки.
Атрибуты
Методы публичного класса
# File lib/csv.rb, line 469
def filter(input=nil, output=nil, **options)
# parse options for input, output, or both
in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
options.each do |key, value|
case key.to_s
when /\Ain(?:put)?_(.+)\Z/
in_options[$1.to_sym] = value
when /\Aout(?:put)?_(.+)\Z/
out_options[$1.to_sym] = value
else
in_options[key] = value
out_options[key] = value
end
end
# build input and output wrappers
input = new(input || ARGF, **in_options)
output = new(output || $stdout, **out_options)
# read, yield, write
input.each do |row|
yield row
output << row
end
end Этот метод предназначен для удобного создания фильтров в стиле Unix для CSV данных. Каждая строка передаётся в предоставленный блок, который может её изменить по мере необходимости. После возвращения из блока строка добавляется к output независимо от изменений.
Аргументы input и output могут быть любыми, что CSV::new() принимает (обычно String или IO объекты). Если они не указаны, по умолчанию используются ARGF и $stdout.
Параметр options также фильтруется до CSV::new() после обработки ключей. Любой ключ, начинающийся с :in_ или :input_, будет иметь этот префикс удалён и будет использоваться только в options Hash для объекта input. Ключи, начинающиеся с :out_ или :output_, влияют только на output. Все остальные ключи назначаются обоим объектам.
Значение :output_row_sep option по умолчанию равно $INPUT_RECORD_SEPARATOR ($/).
# File lib/csv.rb, line 508
def foreach(path, mode="r", **options, &block)
return to_enum(__method__, path, mode, **options) unless block_given?
open(path, mode, **options) do |csv|
csv.each(&block)
end
end Этот метод предназначен для основного интерфейса чтения CSV файлов. Вы передаёте path и любые options параметры для чтения. Каждая строка файла будет передана предоставленному block блоку поочерёдно.
Параметр options может быть любым, что понимает CSV::new(). Этот метод также понимает дополнительный параметр :encoding, который можно использовать для указания Encoding данных в файле для чтения. Этот параметр необходимо указать, если ваши данные не в формате Encoding::default_external(). CSV будет использовать его для определения способа парсинга данных. Можно указать второй Encoding для транскодирования данных при чтении. Например, encoding: "UTF-32BE:UTF-8" будет читать данные UTF-32BE из файла, но транскодировать их в UTF-8 перед парсингом CSV.
# File lib/csv.rb, line 533
def generate(str=nil, **options)
# add a default empty String, if none was given
if str
str = StringIO.new(str)
str.seek(0, IO::SEEK_END)
else
encoding = options[:encoding]
str = +""
str.force_encoding(encoding) if encoding
end
csv = new(str, **options) # wrap
yield csv # yield for appending
csv.string # return final String
end Этот метод оборачивает переданную вами String строку или по умолчанию пустую String в объект CSV, который передаётся в предоставленный блок. В блоке вы можете добавлять CSV строки к String строке, и после выхода из блока возвращается итоговая String строка.
Обратите внимание, что переданная String строка модифицируется этим методом. Используйте dup() перед передачей, если вам нужна новая String строка.
Параметр options может быть любым, что понимает CSV::new(). Этот метод также понимает дополнительный параметр :encoding для указания базового Encoding кодирования для вывода, если не передаётся String строка. CSV нуждается в этой подсказке, если вы планируете выводить данные, несовместимые с ASCII.
# File lib/csv.rb, line 561
def generate_line(row, **options)
options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
str = +""
if options[:encoding]
str.force_encoding(options[:encoding])
elsif field = row.find {|f| f.is_a?(String)}
str.force_encoding(field.encoding)
end
(new(str, **options) << row).string
end Этот метод — это сокращение для преобразования одной строки (Array) в CSV строку в формате String.
Параметр options может быть любым, что понимает CSV::new(). Этот метод понимает дополнительный параметр :encoding для установки базового Encoding кодирования для вывода. Этот метод попытается определить Encoding кодирование из первого не-nil поля в row, если это возможно, но вам может потребоваться использовать этот параметр как резервный план.
Значение :row_sep option по умолчанию равно $INPUT_RECORD_SEPARATOR ($/).
# File lib/csv.rb, line 429
def instance(data = $stdout, **options)
# create a _signature_ for this method call, data object and options
sig = [data.object_id] +
options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
# fetch or create the instance for this signature
@@instances ||= Hash.new
instance = (@@instances[sig] ||= new(data, **options))
if block_given?
yield instance # run block, if given, returning result
else
instance # or return the instance
end
end Этот метод вернёт экземпляр CSV, как и CSV::new(), но экземпляр будет кэширован и возвращаться при последующих вызовах этого метода для того же объекта data (проверяется с помощью Object#object_id()) и тех же options параметров.
Если указан блок, экземпляр передаётся в блок, и значение возврата блока становится значением возврата метода.
# File lib/csv.rb, line 921
def initialize(data,
col_sep: ",",
row_sep: :auto,
quote_char: '"',
field_size_limit: nil,
converters: nil,
unconverted_fields: nil,
headers: false,
return_headers: false,
write_headers: nil,
header_converters: nil,
skip_blanks: false,
force_quotes: false,
skip_lines: nil,
liberal_parsing: false,
internal_encoding: nil,
external_encoding: nil,
encoding: nil,
nil_value: nil,
empty_value: "",
quote_empty: true,
write_converters: nil,
write_nil_value: nil,
write_empty_value: "",
strip: false)
raise ArgumentError.new("Cannot parse nil as CSV") if data.nil?
if data.is_a?(String)
@io = StringIO.new(data)
@io.set_encoding(encoding || data.encoding)
else
@io = data
end
@encoding = determine_encoding(encoding, internal_encoding)
@base_fields_converter_options = {
nil_value: nil_value,
empty_value: empty_value,
}
@write_fields_converter_options = {
nil_value: write_nil_value,
empty_value: write_empty_value,
}
@initial_converters = converters
@initial_header_converters = header_converters
@initial_write_converters = write_converters
@parser_options = {
column_separator: col_sep,
row_separator: row_sep,
quote_character: quote_char,
field_size_limit: field_size_limit,
unconverted_fields: unconverted_fields,
headers: headers,
return_headers: return_headers,
skip_blanks: skip_blanks,
skip_lines: skip_lines,
liberal_parsing: liberal_parsing,
encoding: @encoding,
nil_value: nil_value,
empty_value: empty_value,
strip: strip,
}
@parser = nil
@parser_enumerator = nil
@eof_error = nil
@writer_options = {
encoding: @encoding,
force_encoding: (not encoding.nil?),
force_quotes: force_quotes,
headers: headers,
write_headers: write_headers,
column_separator: col_sep,
row_separator: row_sep,
quote_character: quote_char,
quote_empty: quote_empty,
}
@writer = nil
writer if @writer_options[:write_headers]
end Этот конструктор обернёт объект String или IO, переданный data для чтения и/или записи. В дополнение к методам экземпляра CSV, делегируются несколько методов IO. (См. CSV::open() для полного списка.) Если вы передаёте String для data, вы можете позже получить его (например, после записи в него) с помощью CSV.string().
Обратите внимание, что обернутый String будет расположен в начале (для чтения). Если вы хотите его в конце (для записи), используйте CSV::generate(). Если вы хотите другое позиционирование, передайте вместо этого предварительно настроенный объект StringIO.
Вы можете установить любые параметры чтения и/или записи в options Hash. Доступные опции:
-
:col_sep -
String, размещаемая между каждым полем. ЭтаStringбудет перекодирована вEncodingданных перед анализом. -
:row_sep -
String, добавляемая в конец каждой строки. Это может быть установлено в специальное значение:auto, которое запрашивает, чтобыCSVавтоматически обнаружил это из данных. Автоматическое обнаружение читает данные вперёд, ища следующую последовательность"\r\n","\n"или"\r". Последовательность будет выбрана даже если она встречается в поле в кавычках, предполагая, что у вас будут те же символы конца строки. Если ни одна из этих последовательностей не найдена,dataявляетсяARGF,STDIN,STDOUTилиSTDERR, или поток доступен только для вывода, используется значение по умолчанию$INPUT_RECORD_SEPARATOR($/). Очевидно, что обнаружение занимает некоторое время.Setвручную, если скорость важна. Также обратите внимание, что объектыIOдолжны быть открыты в бинарном режиме в Windows, если эта функция будет использоваться, так как преобразование символов конца строки может вызвать проблемы с возвратом позиции документа в то место, где он находился до чтения вперёд. ЭтаStringбудет перекодирована вEncodingданных перед анализом. -
:quote_char -
Символ, используемый для заключения полей в кавычки. Это должен быть одиночный символ
String. Это полезно для приложений, которые некорректно используют'в качестве символа кавычки вместо правильного".CSVвсегда будет рассматривать двойную последовательность этого символа как экранированную кавычку. ЭтаStringбудет перекодирована вEncodingданных перед анализом. -
:field_size_limit -
Это максимальный размер, на который
CSVбудет читать вперёд, ища закрывающую кавычку для поля. (По правде говоря, он читает до первого символа конца строки за этим размером.) Если кавычка не может быть найдена в пределах лимита,CSVвызоветMalformedCSVError, предполагая, что данные неверны. Вы можете использовать этот лимит, чтобы предотвратить атаки типа DoS на парсер. Однако, этот лимит может привести к сбою легитимного анализа и поэтому по умолчанию установлен вnil, или выключен. -
:converters -
Arrayимён изConvertersHashи/или лямбда-выражений, которые обрабатывают пользовательское преобразование. Одиночный конвертер не обязательно должен находиться вArray. Все встроенные конвертеры пытаются перекодировать поля в UTF-8 перед преобразованием. Преобразование завершится неудачей, если данные не могут быть перекодированы, оставив поле без изменений. -
:unconverted_fields -
Если установлено в
true, метод unconverted_fields() будет добавлен ко всем возвращаемым строкам (ArrayилиCSV::Row), который будет возвращать поля такими, какими они были до преобразования. Обратите внимание, что:headers, предоставленныеArrayилиString, не были полями документа и, таким образом, будут иметь прикреплённый пустойArray. -
:headers -
Если установлено в
:first_rowилиtrue, начальная строка файлаCSVбудет обрабатываться как строка заголовков. Если установлено вArray, содержимое будет использоваться в качестве заголовков. Если установлено вString,Stringвыполняется через вызовCSV::parse_line()с теми же:col_sep,:row_sepи:quote_char, что и у этого экземпляра, для созданияArrayзаголовков. Эта настройка приводит к тому, чтоCSV#shift()возвращает строки как объектыCSV::Rowвместо массивов, аCSV#read()возвращает объектыCSV::TableвместоArrayмассивов. -
:return_headers -
Когда
false, строки заголовков молча пропускаются. Если установлено вtrue, строки заголовков возвращаются в объектеCSV::Rowс идентичными заголовками и полями (за исключением того, что поля не проходят через конвертеры). -
:write_headers -
Когда
trueи:headersустановлены, строка заголовка будет добавлена к выводу. -
:header_converters -
Идентично по функциональности
:converters, за исключением того, что преобразования применяются только к строкам заголовков. Все встроенные конвертеры пытаются перекодировать заголовки в UTF-8 перед преобразованием. Преобразование завершится неудачей, если данные не могут быть перекодированы, оставив заголовок без изменений. -
:skip_blanks -
При установке значения
true,CSVбудет пропускать любые пустые строки. Обратите внимание, что эта настройка не будет пропускать строки, содержащие разделители столбцов, даже если строки не содержат фактических данных. Если вы хотите пропускать строки, содержащие разделители, но не содержащие данных, рассмотрите возможность использования:skip_lines, или проверки fields.compact.empty? для каждой строки. -
:force_quotes -
При установке значения
true,CSVбудет заключать в кавычки все поляCSV, которые он создаёт. -
:skip_lines -
При установке объекта, реагирующего на
match, каждая строка, соответствующая ему, считается комментарием и игнорируется во время анализа. При установке вString, он сначала преобразуется вRegexp. При установке вnilни одна строка не считается комментарием. Если переданный объект не реагирует наmatch, выбрасываетсяArgumentError. -
:liberal_parsing -
При установке значения
true,CSVпопытается разобрать входные данные, не соответствующие RFC 4180, такие как двойные кавычки в нецитируемых полях. -
:nil_value -
При установке объекта, любые значения пустого поля заменяются установленным объектом, а не nil.
-
:empty_value -
При установке объекта, любые значения поля с пустой строкой заменяются установленным объектом.
-
:quote_empty -
При установке значения
true,CSVбудет заключать пустые значения в двойные кавычки. Когдаfalse,CSVбудет выводить пустую строку для пустого значения поля. -
:write_converters -
Преобразует значения в каждой строке с помощью указанного объекта (объектов)
Proc, которые получают значениеStringи возвращают значениеStringилиnil. Когда указан массив, каждый конвертер будет применён по порядку. -
:write_nil_value -
При значении
String, значение (значения)nilв каждой строке будут заменены указанным значением. -
:write_empty_value -
При значении
Stringилиnil, пустое значение (значения) в каждой строке будут заменены указанным значением. -
:strip -
При установке значения
true,CSVудалит «trnfv» вокруг значений. Если вы укажете строку вместоtrue,CSVудалит строку. Длина строки должна быть 1.
См. CSV::DEFAULT_OPTIONS для настроек по умолчанию.
Параметры не могут быть переопределены в методах экземпляра по причинам производительности, поэтому обязательно установите здесь то, что вам нужно.
# File lib/csv.rb, line 635
def open(filename, mode="r", **options)
# wrap a File opened with the remaining +args+ with no newline
# decorator
file_opts = {universal_newline: false}.merge(options)
begin
f = File.open(filename, mode, **file_opts)
rescue ArgumentError => e
raise unless /needs binmode/.match?(e.message) and mode == "r"
mode = "rb"
file_opts = {encoding: Encoding.default_external}.merge(file_opts)
retry
end
begin
csv = new(f, **options)
rescue Exception
f.close
raise
end
# handle blocks like Ruby's open(), not like the CSV library
if block_given?
begin
yield csv
ensure
csv.close
end
else
csv
end
end Этот метод открывает объект IO и оборачивает его с помощью CSV. Он предназначен в качестве основного интерфейса для записи файла CSV.
Вы должны передать filename и можете необязательно добавить mode для функции open() в Ruby. Вы также можете передать необязательный Hash, содержащий любые options значения, которые понимает CSV::new() в качестве конечного аргумента.
Этот метод работает аналогично вызову open() в Ruby, при этом он передаёт объект CSV в предоставленный блок и закрывает его по завершении блока, или он возвращает объект CSV, когда блок не предоставлен. (Примечание: это отличается от библиотеки CSV Ruby 1.8, которая передавала строки в блок. Используйте CSV::foreach() для такого поведения.)
Вы должны предоставить mode с встроенным указателем Encoding, если только ваши данные не в формате Encoding::default_external(). CSV проверит Encoding объекта базового IO (установленный передаваемым вами mode) для определения способа парсинга данных. Вы можете предоставить второй Encoding для преобразования данных по мере чтения, как вы можете сделать с обычным вызовом IO::open(). Например, "rb:UTF-32BE:UTF-8" будет читать данные UTF-32BE из файла, но преобразовывать их в UTF-8 перед тем, как CSV обработает их.
Открытый объект CSV делегирует многие методы IO для удобства. Вы можете вызвать:
# File lib/csv.rb, line 679
def parse(str, **options, &block)
csv = new(str, **options)
return csv.each(&block) if block_given?
# slurp contents, if no block is given
begin
csv.read
ensure
csv.close
end
end Этот метод может быть использован для простого разбора CSV из String. Вы можете предоставить block, который будет вызываться с каждой строкой String поочерёдно, или просто использовать возвращённый Array массивов (если block не указан).
Вы передаёте str для чтения и необязательный options, содержащий всё, что CSV::new() понимает.
# File lib/csv.rb, line 699 def parse_line(line, **options) new(line, **options).shift end
Этот метод является сокращением для преобразования одной строки CSV String в Array. Обратите внимание, что если line содержит несколько строк, всё, что находится за первой строкой, игнорируется.
Параметр options может быть любым, что CSV::new() понимает.
# File lib/csv.rb, line 714
def read(path, **options)
open(path, **options) { |csv| csv.read }
end Используйте для считывания файла CSV в Array массивов. Передайте path в файл и любые options значения, которые CSV::new() понимает. Этот метод также понимает дополнительный параметр :encoding, который можно использовать для указания Encoding данных в файле для чтения. Вы должны предоставить его, если только ваши данные не в формате Encoding::default_external(). CSV будет использовать это для определения способа парсинга данных. Вы можете предоставить второй Encoding для преобразования данных по мере чтения. Например, encoding: "UTF-32BE:UTF-8" будет читать данные UTF-32BE из файла, но преобразовывать их в UTF-8 перед тем, как CSV обработает их.
# File lib/csv.rb, line 719 def readlines(path, **options) read(path, **options) end
Псевдоним для CSV::read().
# File lib/csv.rb, line 730
def table(path, **options)
default_options = {
headers: true,
converters: :numeric,
header_converters: :symbol,
}
options = default_options.merge(options)
read(path, **options)
end Сокращение для:
CSV.read( path, { headers: true,
converters: :numeric,
header_converters: :symbol }.merge(options) )
Общедоступные методы экземпляра
# File lib/csv.rb, line 1229 def <<(row) writer << row self end
Основной метод записи для обернутых строк и ввода-вывода, row (массив Array или CSV::Row) преобразуется в CSV и добавляется к источнику данных. При передаче CSV::Row добавляются только поля строки fields().
Источник данных должен быть открыт для записи.
# File lib/csv.rb, line 1161
def binmode?
if @io.respond_to?(:binmode?)
@io.binmode?
else
false
end
end # File lib/csv.rb, line 1008 def col_sep parser.column_separator end
Кодированный :col_sep используемый в чтении и записи. Подробности см. в CSV::new.
# File lib/csv.rb, line 1251 def convert(name = nil, &converter) parser_fields_converter.add_converter(name, &converter) end
Этот метод позволяет установить встроенный CSV::Converters или предоставить блок для обработки пользовательской конвертации.
Если вы предоставляете блок с одним аргументом, ему будет передано поле, и он должен вернуть преобразованное значение или само поле. Если ваш блок принимает два аргумента, ему также будет передана CSV::FieldInfo Struct, содержащая подробности о поле. В этом случае блок должен вернуть преобразованное поле или само поле.
# File lib/csv.rb, line 1049
def converters
parser_fields_converter.map do |converter|
name = Converters.rassoc(converter)
name ? name.first : converter
end
end Возвращает текущий список примененных конвертеров. Подробности см. в CSV::new. Встроенные конвертеры будут возвращены по имени, а другие — как есть.
# File lib/csv.rb, line 1279 def each(&block) parser_enumerator.each(&block) end
Поочерёдно выводит каждую строку источника данных.
Поддержка Enumerable.
Источник данных должен быть открыт для чтения.
# File lib/csv.rb, line 1197
def eof?
return false if @eof_error
begin
parser_enumerator.peek
false
rescue MalformedCSVError => error
@eof_error = error
false
rescue StopIteration
true
end
end # File lib/csv.rb, line 1032 def field_size_limit parser.field_size_limit end
Предел размера поля, если таковой имеется. Подробности см. в CSV::new.
# File lib/csv.rb, line 1169 def flock(*args) raise NotImplementedError unless @io.respond_to?(:flock) @io.flock(*args) end
# File lib/csv.rb, line 1117 def force_quotes? @writer_options[:force_quotes] end
Возвращает true если все выходные поля заключены в кавычки. Подробности см. в CSV::new.
# File lib/csv.rb, line 1266 def header_convert(name = nil, &converter) header_fields_converter.add_converter(name, &converter) end
Идентично CSV#convert(), но для заголовочных строк.
Обратите внимание, что этот метод необходимо вызвать до чтения заголовочных строк для его действия.
# File lib/csv.rb, line 1101
def header_converters
header_fields_converter.map do |converter|
name = HeaderConverters.rassoc(converter)
name ? name.first : converter
end
end Возвращает текущий список конвертеров, используемых для заголовков. Подробности см. в CSV::new. Встроенные конвертеры будут возвращены по имени, а другие — как есть.
# File lib/csv.rb, line 1299 def header_row? parser.header_row? end
Возвращает true если следующая считанная строка будет заголовочной строкой.
# File lib/csv.rb, line 1069
def headers
if @writer
@writer.headers
else
parsed_headers = parser.headers
return parsed_headers if parsed_headers
raw_headers = @parser_options[:headers]
raw_headers = nil if raw_headers == false
raw_headers
end
end Возвращает nil если заголовки не будут использоваться, true если они будут, но ещё не были считаны, или фактические заголовки после их чтения. Подробности см. в CSV::new.
# File lib/csv.rb, line 1328
def inspect
str = ["#<", self.class.to_s, " io_type:"]
# show type of wrapped IO
if @io == $stdout then str << "$stdout"
elsif @io == $stdin then str << "$stdin"
elsif @io == $stderr then str << "$stderr"
else str << @io.class.to_s
end
# show IO.path(), if available
if @io.respond_to?(:path) and (p = @io.path)
str << " io_path:" << p.inspect
end
# show encoding
str << " encoding:" << @encoding.name
# show other attributes
["lineno", "col_sep", "row_sep", "quote_char"].each do |attr_name|
if a = __send__(attr_name)
str << " " << attr_name << ":" << a.inspect
end
end
["skip_blanks", "liberal_parsing"].each do |attr_name|
if a = __send__("#{attr_name}?")
str << " " << attr_name << ":" << a.inspect
end
end
_headers = headers
str << " headers:" << _headers.inspect if _headers
str << ">"
begin
str.join('')
rescue # any encoding error
str.map do |s|
e = Encoding::Converter.asciicompat_encoding(s.encoding)
e ? s.encode(e) : s.force_encoding("ASCII-8BIT")
end.join('')
end
end Возвращает упрощённое описание ключевых атрибутов CSV в ASCII-совместимой String.
# File lib/csv.rb, line 1174 def ioctl(*args) raise NotImplementedError unless @io.respond_to?(:ioctl) @io.ioctl(*args) end
# File lib/csv.rb, line 1122 def liberal_parsing? parser.liberal_parsing? end
Возвращает true если некорректный ввод обрабатывается. Подробности см. в CSV::new.
# File lib/csv.rb, line 1147 def line parser.line end
Последняя прочитанная строка из этого файла.
# File lib/csv.rb, line 1136
def lineno
if @writer
@writer.lineno
else
parser.lineno
end
end Номер строки последней прочитанной строки из этого файла. Поля с вложенными символами конца строки не повлияют на этот счётчик.
# File lib/csv.rb, line 1179 def path @io.path if @io.respond_to?(:path) end
# File lib/csv.rb, line 1024 def quote_char parser.quote_character end
Кодированный :quote_char символ, используемый при парсинге и записи. Подробнее см. CSV::new.
# File lib/csv.rb, line 1288
def read
rows = to_a
if parser.use_headers?
Table.new(rows, headers: parser.headers)
else
rows
end
end Считывает оставшиеся строки и возвращает массив массивов Array.
Источник данных должен быть открыт для чтения.
# File lib/csv.rb, line 1084 def return_headers? parser.return_headers? end
Возвращает true, если заголовки будут возвращены как строка результатов. Подробнее см. CSV::new.
# File lib/csv.rb, line 1212 def rewind @parser = nil @parser_enumerator = nil @eof_error = nil @writer.rewind if @writer @io.rewind end
Перематывает объект IO и сбрасывает счётчик строк CSV.
# File lib/csv.rb, line 1016 def row_sep parser.row_separator end
Кодированный :row_sep символ, используемый при парсинге и записи. Подробнее см. CSV::new.
# File lib/csv.rb, line 1310
def shift
if @eof_error
eof_error, @eof_error = @eof_error, nil
raise eof_error
end
begin
parser_enumerator.next
rescue StopIteration
nil
end
end Основной метод чтения для обернутых строк и ввода-вывода, из источника данных извлекается одна строка, анализируется и возвращается как массив Array полей (если не используются заголовки строк) или объект CSV::Row (при использовании заголовков строк).
Источник данных должен быть открыт для чтения.
# File lib/csv.rb, line 1112 def skip_blanks? parser.skip_blanks? end
Возвращает true, если пустые строки пропускаются анализатором. Подробнее см. CSV::new.
# File lib/csv.rb, line 1040 def skip_lines parser.skip_lines end
Регулярное выражение, обозначающее строку как комментарий. Подробнее см. CSV::new.
# File lib/csv.rb, line 1183 def stat(*args) raise NotImplementedError unless @io.respond_to?(:stat) @io.stat(*args) end
# File lib/csv.rb, line 1188 def to_i raise NotImplementedError unless @io.respond_to?(:to_i) @io.to_i end
# File lib/csv.rb, line 1193 def to_io @io.respond_to?(:to_io) ? @io.to_io : @io end
# File lib/csv.rb, line 1060 def unconverted_fields? parser.unconverted_fields? end
Возвращает true, если unconverted_fields() преобразуется в результаты парсинга. Подробнее см. CSV::new.
# File lib/csv.rb, line 1092 def write_headers? @writer_options[:write_headers] end
Возвращает true, если заголовки пишутся в выходные данные. Подробнее см. CSV::new.
Приватные методы экземпляра
# File lib/csv.rb, line 1460
def build_fields_converter(initial_converters, options)
fields_converter = FieldsConverter.new(options)
normalize_converters(initial_converters).each do |name, converter|
fields_converter.add_converter(name, &converter)
end
fields_converter
end # File lib/csv.rb, line 1442
def build_header_fields_converter
specific_options = {
builtin_converters: HeaderConverters,
accept_nil: true,
}
options = @base_fields_converter_options.merge(specific_options)
build_fields_converter(@initial_header_converters, options)
end # File lib/csv.rb, line 1430
def build_parser_fields_converter
specific_options = {
builtin_converters: Converters,
}
options = @base_fields_converter_options.merge(specific_options)
build_fields_converter(@initial_converters, options)
end # File lib/csv.rb, line 1455
def build_writer_fields_converter
build_fields_converter(@initial_write_converters,
@write_fields_converter_options)
end # File lib/csv.rb, line 1405
def convert_fields(fields, headers = false)
if headers
header_fields_converter.convert(fields, nil, 0)
else
parser_fields_converter.convert(fields, @headers, lineno)
end
end Обрабатывает fields с помощью @converters, или @header_converters если headers передано как true, возвращая преобразованный набор полей. Любой конвертер, изменяющий поле на что-то, кроме String, останавливает цепочку преобразования для этого поля. Это в первую очередь оптимизация.
# File lib/csv.rb, line 1368
def determine_encoding(encoding, internal_encoding)
# honor the IO encoding if we can, otherwise default to ASCII-8BIT
io_encoding = raw_encoding
return io_encoding if io_encoding
return Encoding.find(internal_encoding) if internal_encoding
if encoding
encoding, = encoding.split(":", 2) if encoding.is_a?(String)
return Encoding.find(encoding)
end
Encoding.default_internal || Encoding.default_external
end # File lib/csv.rb, line 1438 def header_fields_converter @header_fields_converter ||= build_header_fields_converter end
# File lib/csv.rb, line 1383
def normalize_converters(converters)
converters ||= []
unless converters.is_a?(Array)
converters = [converters]
end
converters.collect do |converter|
case converter
when Proc # custom code block
[nil, converter]
else # by name
[converter, nil]
end
end
end # File lib/csv.rb, line 1468 def parser @parser ||= Parser.new(@io, parser_options) end
# File lib/csv.rb, line 1477 def parser_enumerator @parser_enumerator ||= parser.parse end
# File lib/csv.rb, line 1426 def parser_fields_converter @parser_fields_converter ||= build_parser_fields_converter end
# File lib/csv.rb, line 1472
def parser_options
@parser_options.merge(header_fields_converter: header_fields_converter,
fields_converter: parser_fields_converter)
end # File lib/csv.rb, line 1416
def raw_encoding
if @io.respond_to? :internal_encoding
@io.internal_encoding || @io.external_encoding
elsif @io.respond_to? :encoding
@io.encoding
else
nil
end
end Возвращает кодировку внутреннего объекта IO.
# File lib/csv.rb, line 1481 def writer @writer ||= Writer.new(@io, writer_options) end
# File lib/csv.rb, line 1451 def writer_fields_converter @writer_fields_converter ||= build_writer_fields_converter end
# File lib/csv.rb, line 1485
def writer_options
@writer_options.merge(header_fields_converter: header_fields_converter,
fields_converter: writer_fields_converter)
end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.