【问题标题】:Ruby CSV - Write on same row without overwriting?Ruby CSV - 写在同一行而不覆盖?
【发布时间】:2021-03-12 21:03:38
【问题描述】:

我正在使用

CSV.open(filename, "w") do |csv| 在一个 ruby​​.rb 文件中创建并写入 csv 文件,现在我需要打开它并在第二个 .rb 文件中对其进行编辑。现在我正在使用CSV.open(filename, "a") do |csv|,但这会创建新行而不是将新内容添加到现有行的末尾。

如果我第二次使用CSV.open(filename, "w") do |csv|,它会覆盖第一行。

编辑:

# Create export CSV
final_export_csv = "filepath_final.csv"

# Create filename for CSV file
imported_csv_filename = "imported_file.csv"

CSV.open(final_export_csv, "w", headers: ["several", "headers"] + [:new_header], write_headers: true) do |final_csv|

  # Read existing CSV file
  CSV.foreach(imported_csv_filename) do |old_csv_row|

    # Read a row, add the new column, write it to the new row
    CSV.open(denominator_csv_filename, "r+") do |new_csv_col|


# gathering some data code

          data = { passed.in }

          # Write data
     
          new_csv_col <<
          [
            passedin[:data]
          ]

          old_csv_row[:new_header] = passedin[:data]
          final_export_csv << old_csv_row

        end
      end
    end
  end
end

【问题讨论】:

  • 您无法轻松地就地重写文本文件。您需要将其全部读入,然后在进行任何修改后将其全部写回。
  • 如果你只是想添加另一个名为"new_col"的列,其元素由数组arr给出,你可以使用普通的文件方法:File.open('out', 'w') do |fout|; File.foreach('in', chomp: true).with_index { |line,i| fputs ',' + line + i.zero? ? "new_col" : arr[i-1] }; end

标签: ruby csv


【解决方案1】:

As tadman comments,您实际上无法就地编辑文件。好吧,您可以,但所有行都必须保持相同的长度。你没有这样做。

相反,读取一行,修改它,然后将其写入新的 CSV。然后用新文件替换旧文件。小心避免将整个 CSV 塞入内存,CSV 文件可能会变得非常大。

require 'csv'
require 'tempfile'
require 'fileutils'

csv_file = "test.csv"
# Write the new file to a tempfile to avoid polluting the directory.
temp = Tempfile.new

# Read the header line.
old_csv = CSV.open(csv_file, "r", headers: true, return_headers: true)
old_csv.readline

# Open the new CSV with the existing headers plus a new one.
new_csv = CSV.open(
  temp, "w",
  headers: old_csv.headers + [:new],
  write_headers: true
)

# Read a row, add the new column, write it to the new CSV.
old_csv.each do |row|
  row[:new] = 42
  new_csv << row
end

old_csv.close
new_csv.close

# Replace the old CSV with the new one.
FileUtils.move(temp.path, csv_file)

【讨论】:

  • # Open the new CSV with the existing headers plus a new one. new_csv = CSV.open( temp, "w", headers: old_csv.headers + [:new], write_headers: true ) # Read a row, add the new column, write it to the new CSV. old_csv.each do |row| row[:new] = 42 new_csv &lt;&lt; row end 你在用 [:new] 标头做什么?我不确定我是否理解。
  • @TaylorDorsett 将新内容添加到行尾。列标题是“新的”。
  • 有没有办法在没有 tempfile 和 fileutils 的情况下做到这一点?当我尝试这个时,我得到一个关于尝试转换为字符串的错误类型错误。
  • @TaylorDorsett 是的,您可以使用常规文件。但是错误在哪里?是CSV.open(temp, ...)吗?试试temp.path
  • @TaylorDorsett 在哪几行?什么版本的 Ruby?
猜你喜欢
  • 2014-12-28
  • 2014-03-21
  • 1970-01-01
  • 2013-03-15
  • 2018-04-17
  • 2014-02-05
  • 1970-01-01
  • 2016-03-02
相关资源
最近更新 更多