【问题标题】:RubyZip Unzipping .docx, modifying, and zipping back up throws Errno::EACCESS errorRubyZip 解压缩 .docx、修改和压缩备份会引发 Errno::EACCESS 错误
【发布时间】:2015-05-31 07:22:08
【问题描述】:

所以,我正在使用 Nokogiri 和 Rubyzip 解压缩 .docx 文件,修改其中的 word/docoument.xml 文件(在这种情况下,只需将包含的每个元素更改为“梦想!”),然后压缩备份。

require 'nokogiri'
require 'zip'

zip = Zip::File.open("apple.docx")
doc = zip.find_entry("word/document.xml")

xml = Nokogiri::XML.parse(doc.get_input_stream)

inputs = xml.root.xpath("//w:t")

inputs.each{|element| element.content = "DREAMS!"}

zip.get_output_stream("word/document.xml", "w") {|f| f.write(xml.to_s)}

zip.close

通过 IRB 逐行运行代码可以完美运行,并根据需要对 .docx 文件进行更改,但如果我从命令行运行脚本

ruby xmltodoc.rb   

我收到以下错误:

C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:416:in `rename': Permission denied - (C:/Users/Bane/De
sktop/apple.docx20150326-6016-k9ff1n, apple.docx) (Errno::EACCES)
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:416:in `on_success_replace'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:308:in `commit'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rubyzip-1.1.7/lib/zip/file.rb:332:in `close'
        from ./xmltodoc.rb:15:in `<main>' 

我计算机上的所有用户都拥有该 .docx 文件的所有权限。该文件也没有任何特殊设置——只是一个带有段落的新文件。此错误仅显示在 Windows 上,但该脚本在 Mac 和 Ubuntu 上完美运行。以管理员身份运行 Powershell 会引发相同的错误。有什么想法吗?

【问题讨论】:

  • 欢迎来到 Stack Overflow。为什么这是一个 Nokogiri 问题?它与读取或写入文件时的权限无关。我正在删除标签。要调试您的代码,请删除对 Nokogiri 的所有引用,然后打开并保存文件并查看问题是否仍然存在。

标签: ruby windows file-permissions rubyzip


【解决方案1】:

在我的 Windows 7 系统上,以下工作。

require 'nokogiri'
require 'zip'

Zip::File.open("#{File.dirname(__FILE__)}/apple.docx") do |zipfile|
  doc = zipfile.read("word/document.xml")
  xml = Nokogiri::XML.parse(doc)
  inputs = xml.root.xpath("//w:t")
  inputs.each{|element| element.content = "DREAMS!"}
  zipfile.get_output_stream("word/document.xml") {|f| f.write(xml.to_s)}
end

您也可以使用 gem docx,这是一个示例,书签的名称是荷兰语,因为那是我的 MS Office 使用的语言。

require 'docx'

# Create a Docx::Document object for our existing docx file
doc = Docx::Document.open('C:\Users\Gebruiker\test.docx'.gsub(/\\/,'/'))

# Insert a single line of text after one of our bookmarks
# p doc.bookmarks['bladwijzer1'].methods
doc.bookmarks['bladwijzer1'].insert_text_after("Hello world.")

# Insert multiple lines of text at our bookmark
doc.bookmarks['bladwijzer3'].insert_multiple_lines(['Hello', 'World', 'foo'])

# Save document to specified path
doc.save('example-edited.docx')

【讨论】:

  • 这很完美!谢谢!但我很好奇,你知道为什么我的代码可以在 Mac 和 Ubuntu 上运行,但不能在 Windows 上运行吗?我认为 'zip.close' 存在问题,但 Zip::File.open 在完成其块后没有自动 .close 吗?为什么我的代码可以在 IRB 中工作,但从命令行调用文件时却不行?无论如何,谢谢!
  • 我想这是 IRB 中不会发生的时间问题,临时文件在 zip 仍然存在时被重命名为 zip,无论如何最好使用打开和关闭的块自动生成一个文件,我也应该尝试使用我的 docx 示例来做到这一点
猜你喜欢
  • 1970-01-01
  • 2023-04-06
  • 2019-01-29
  • 2014-12-07
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多