класс 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,Engeneering,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 468
def self.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 507
def self.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 532
def self.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, когда не передаётся String, для установки базового Encoding для вывода. CSV нуждается в этой подсказке, если вы планируете выводить несовместимые с ASCII данные.
# File lib/csv.rb, line 560
def self.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 Этот метод — сокращённая запись для преобразования одной строки (массива) в CSV String.
Параметр options может быть любым, что CSV::new() понимает. Этот метод понимает дополнительный параметр :encoding, чтобы установить базовый Encoding для вывода. Этот метод попытается угадать ваш Encoding из первого не-nil поля в row, если это возможно, но вам может потребоваться использовать этот параметр как резервный вариант.
Параметр :row_sep option по умолчанию равен $INPUT_RECORD_SEPARATOR ($/).
# File lib/csv.rb, line 428
def self.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 898
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?
# create the IO object we will read from
@io = data.is_a?(String) ? StringIO.new(data) : data
@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
@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 -
Массив имён из
ConvertersHashи/или лямбда-выражений, которые обрабатывают пользовательское преобразование. Один преобразователь не обязательно должен быть в массиве. Все встроенные преобразователи пытаются преобразовать поля в UTF-8 перед преобразованием. Преобразование завершится неудачей, если данные не могут быть преобразованы, оставив поле неизменённым. -
:unconverted_fields -
Если установлено значение
true, будет добавлен метод unconverted_fields(), который будет возвращать поля в виде, в котором они были до преобразования для всех возвращаемых строк (массива илиCSV::Row). Обратите внимание, что:headers, предоставленныйArrayилиString, не являлись полями документа и, следовательно, имеют прикреплённый пустой массив. -
:headers -
Если установлено значение
:first_rowилиtrue, первая строка файлаCSVбудет рассматриваться как строка заголовков. Если установлено значение массива, его содержимое будет использоваться как заголовки. Если установлено значение строки, строка заголовков обрабатывается вызовомCSV::parse_line()с теми же:col_sep,:row_sep, и:quote_char, что и этот экземпляр, чтобы получить массив заголовков. Это значение заставляетCSV#shift()возвращать строки в виде объектовCSV::Row, аCSV#read()- объектыCSV::Tableвместо массива массивов. -
:return_headers -
При
false, строки заголовков игнорируются. Если установлено значениеtrue, строки заголовков возвращаются в объектеCSV::Rowс идентичными заголовками и полями (за исключением того, что поля не проходят через преобразователи). -
:write_headers -
При
trueи:headers, в выходной файл будет добавлена строка заголовков. -
:header_converters -
Функционально идентично
:converters, за исключением того, что преобразования применяются только к строкам заголовков. Все встроенные преобразователи пытаются преобразовать заголовки в UTF-8 перед преобразованием. Преобразование завершится неудачей, если данные не могут быть преобразованы, оставив заголовок неизменённым. -
:skip_blanks -
Если установлено значение
true,CSVпропустит пустые строки. Обратите внимание, что это значение не будет пропускать строки, содержащие разделители столбцов, даже если в строках нет фактических данных. Если вы хотите пропустить строки, содержащие разделители, но не содержащие содержимого, воспользуйтесь:skip_lines, или проверьте, пуст ли результат compact.empty? для каждого поля в строке. -
:force_quotes -
Если установлено значение
true,CSVбудет заключать всеCSVполя, которые он создаёт. -
:skip_lines -
При установке объекта, отвечающего за
match, все строки, соответствующие ей, считаются комментариями и игнорируются во время разбора. При установке строки, она сначала преобразуется вRegexp. При установке значенияnilни одна строка не считается комментарием. Если переданный объект не отвечает заmatch, выбрасываетсяArgumentError. -
:liberal_parsing -
При установке значения
true,CSVпопытается разобрать входные данные, не соответствующие RFC 4180, например, двойные кавычки в нецитируемых полях. -
:nil_value -
При установке объекта любые значения пустых полей заменяются на установленный объект, а не на nil.
-
:empty_value -
При установке объекта, любые значения пустой строковой поля заменяются на установленный объект.
-
:quote_empty -
TODO
-
:write_converters -
TODO
-
:write_nil_value -
TODO
-
:write_empty_value -
TODO
-
:strip -
TODO
См. CSV::DEFAULT_OPTIONS для значений по умолчанию.
Параметры нельзя переопределить в методах экземпляров по причинам производительности, поэтому убедитесь, что вы установили желаемые значения здесь.
# File lib/csv.rb, line 634
def self.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 при отсутствии блока. (Примечание: Это отличается от библиотеки Ruby 1.8 CSV, которая передавала строки в блок. Используйте 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 678
def self.parse(*args, &block)
csv = new(*args)
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 698 def self.parse_line(line, **options) new(line, options).shift end
Этот метод является сокращением для преобразования одной строки CSV String в массив Array. Обратите внимание, что если line содержит несколько строк, всё, что находится за первой строкой, игнорируется.
Параметр options может быть любым, что понимает CSV::new().
# File lib/csv.rb, line 713
def self.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 718 def self.readlines(*args) read(*args) end
Псевдоним для CSV::read().
# File lib/csv.rb, line 729
def self.table(path, **options)
read( path, { headers: true,
converters: :numeric,
header_converters: :symbol }.merge(options) )
end Сокращение для:
CSV.read( path, { headers: true,
converters: :numeric,
header_converters: :symbol }.merge(options) )
Общедоступные методы экземпляров
# File lib/csv.rb, line 1185 def <<(row) writer << row self end
Основной метод записи для обернутых строк и ввода-вывода, row (массив Array или CSV::Row) преобразуется в CSV и добавляется к источнику данных. При передаче CSV::Row добавляются только поля строки fields().
Источник данных должен быть открыт для записи.
# File lib/csv.rb, line 1122
def binmode?
if @io.respond_to?(:binmode?)
@io.binmode?
else
false
end
end # File lib/csv.rb, line 979 def col_sep parser.column_separator end
Закодированный :col_sep, используемый при разборе и записи. См. CSV::new для подробностей.
# File lib/csv.rb, line 1207 def convert(name = nil, &converter) parser_fields_converter.add_converter(name, &converter) end
Можно использовать этот метод для установки встроенного CSV::Converters или для предоставления блока, обрабатывающего пользовательское преобразование.
Если вы предоставляете блок с одним аргументом, ему будет передано поле, и ожидается, что он вернет преобразованное значение или само поле. Если ваш блок принимает два аргумента, ему также будет передана CSV::FieldInfo Struct, содержащая подробности о поле. Опять же, блок должен вернуть преобразованное поле или само поле.
# File lib/csv.rb, line 1014
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 1235 def each(&block) parser_enumerator.each(&block) end
Возвращает каждую строку источника данных по очереди.
Поддержка Enumerable.
Источник данных должен быть открыт для чтения.
# File lib/csv.rb, line 1158
def eof?
begin
parser_enumerator.peek
false
rescue StopIteration
true
end
end # File lib/csv.rb, line 1000 def field_size_limit parser.field_size_limit end
Предел размера поля, если таковой имеется. См. CSV::new для подробностей.
# File lib/csv.rb, line 1130 def flock(*args) raise NotImplementedError unless @io.respond_to?(:flock) @io.flock(*args) end
# File lib/csv.rb, line 1078 def force_quotes? @writer_options[:force_quotes] end
Возвращает true если все поля вывода заключены в кавычки. См. CSV::new для подробностей.
# File lib/csv.rb, line 1222 def header_convert(name = nil, &converter) header_fields_converter.add_converter(name, &converter) end
Идентично CSV#convert(), но для заголовочных строк.
Обратите внимание, что этот метод необходимо вызвать перед чтением заголовочных строк, чтобы он имел какой-либо эффект.
# File lib/csv.rb, line 1062
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 1255 def header_row? parser.header_row? end
Возвращает true если следующая считываемая строка будет заголовочной строкой.
# File lib/csv.rb, line 1033
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 1280
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 1135 def ioctl(*args) raise NotImplementedError unless @io.respond_to?(:ioctl) @io.ioctl(*args) end
# File lib/csv.rb, line 1083 def liberal_parsing? parser.liberal_parsing? end
Возвращает true если недопустимый ввод обрабатывается. См. CSV::new для подробностей.
# File lib/csv.rb, line 1108 def line parser.line end
Последняя прочитанная строка из этого файла.
# File lib/csv.rb, line 1097
def lineno
if @writer
@writer.lineno
else
parser.lineno
end
end Номер строки последней прочитанной строки из этого файла. Поля с вложенными символами конца строки не повлияют на этот счетчик.
# File lib/csv.rb, line 1140 def path @io.path if @io.respond_to?(:path) end
# File lib/csv.rb, line 995 def quote_char parser.quote_character end
Кодированный символ :quote_char используемый при разборе и записи. См. CSV::new для получения подробностей.
# File lib/csv.rb, line 1244
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 1048 def return_headers? parser.return_headers? end
Возвращает true , если заголовки будут возвращены как строка результатов. См. CSV::new для получения подробностей.
# File lib/csv.rb, line 1169 def rewind @parser = nil @parser_enumerator = nil @writer.rewind if @writer @io.rewind end
Перематывает объект IO и сбрасывает счётчик строк CSV.
# File lib/csv.rb, line 987 def row_sep parser.row_separator end
Кодированный символ :row_sep , используемый при разборе и записи. См. CSV::new для получения подробностей.
# File lib/csv.rb, line 1266
def shift
begin
parser_enumerator.next
rescue StopIteration
nil
end
end Основной метод чтения для обернутых строк и ввода/вывода, из источника данных извлекается одна строка, анализируется и возвращается как Array полей (если заголовки не используются) или как CSV::Row (при использовании заголовков строк).
Источник данных должен быть открыт для чтения.
# File lib/csv.rb, line 1073 def skip_blanks? parser.skip_blanks? end
Возвращает true пустые строки пропускаются анализатором. См. CSV::new для получения подробностей.
# File lib/csv.rb, line 1005 def skip_lines parser.skip_lines end
Регулярное выражение, отмечающее строку как комментарий. См. CSV::new для получения подробностей
# File lib/csv.rb, line 1144 def stat(*args) raise NotImplementedError unless @io.respond_to?(:stat) @io.stat(*args) end
# File lib/csv.rb, line 1149 def to_i raise NotImplementedError unless @io.respond_to?(:to_i) @io.to_i end
# File lib/csv.rb, line 1154 def to_io @io.respond_to?(:to_io) ? @io.to_io : @io end
# File lib/csv.rb, line 1024 def unconverted_fields? parser.unconverted_fields? end
Возвращает true если unconverted_fields() преобразуются в результаты разбора. См. CSV::new для получения подробностей.
# File lib/csv.rb, line 1053 def write_headers? @writer_options[:write_headers] end
Возвращает true если заголовки записываются в выходные данные. См. CSV::new для получения подробностей.
Методы частного экземпляра
# File lib/csv.rb, line 1412
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 1394
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 1382
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 1407
def build_writer_fields_converter
build_fields_converter(@initial_write_converters,
@write_fields_converter_options)
end # File lib/csv.rb, line 1357
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 1320
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 1390 def header_fields_converter @header_fields_converter ||= build_header_fields_converter end
# File lib/csv.rb, line 1335
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 1420 def parser @parser ||= Parser.new(@io, parser_options) end
# File lib/csv.rb, line 1429 def parser_enumerator @parser_enumerator ||= parser.parse end
# File lib/csv.rb, line 1378 def parser_fields_converter @parser_fields_converter ||= build_parser_fields_converter end
# File lib/csv.rb, line 1424
def parser_options
@parser_options.merge(header_fields_converter: header_fields_converter,
fields_converter: parser_fields_converter)
end # File lib/csv.rb, line 1368
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 1433 def writer @writer ||= Writer.new(@io, writer_options) end
# File lib/csv.rb, line 1403 def writer_fields_converter @writer_fields_converter ||= build_writer_fields_converter end
# File lib/csv.rb, line 1437
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.