简体   繁体   English

在Windows上使用Ruby读取PNG文件失败

[英]Failure reading PNG files with Ruby on Windows

I am creating a Zip file containing both text files and image files. 我正在创建一个包含文本文件和图像文件的Zip文件。 The code works as expected when running on MacOS, but it fails when running on Windows because the image file contents are not read correctly. 代码在MacOS上运行时按预期工作,但在Windows上运行时失败,因为图像文件内容无法正确读取。

The snippet below always reads PNG image files as '‰PNG', adding a 5 bytes file in the Zip for each PNG image. 下面的代码段总是将PNG图像文件读作'‰PNG',在Zip中为每个PNG图像添加一个5字节的文件。

Is it an issue regarding Windows environment? 这是关于Windows环境的问题吗?

zip_fs.file.open(destination, 'w') do |f|
  f.write File.read(file_name)
end

from Why are binary files corrupted when zipping them? 来自为什么压缩它们时二进制文件被破坏了?

io.get_output_stream(zip_file_path) do |out|
  out.write File.binread(disk_file_path)
end

You need to tell Ruby to read/write the files in binary mode. 您需要告诉Ruby以二进制模式读/写文件。 Here are some variations on a theme: 以下是主题的一些变体:

zip_fs.file.open(destination, 'wb') do |f|
  File.open(file_name, 'rb') do |fi|
    f.write fi.read
  end
end

zip_fs.file.open(destination, 'wb') do |f|
  f.write File.read(file_name, 'mode' => 'rb')
end

zip_fs.file.open(destination, 'wb') do |f|
  f.write File.readbin(file_name)
end

A potential problem with the code is the input file is being slurped, which, if it's larger than the available space, would be a bad thing. 代码的一个潜在问题是输入文件正在被玷污,如果它比可用空间大,那将是一件坏事。 It'd be better to read the input file in blocks. 以块为单位读取输入文件会更好。 This is untested but should work: 这是未经测试但应该有效:

BLOCK_SIZE = 1024 * 1024
zip_fs.file.open(destination, 'wb') do |f|
  File.open(file_name, 'rb') do |fi|
    while (block_in = fi.read(BLOCK_SIZE)) do
      f.write block_in
    end
  end
end

The file that was opened will never be closed. 打开的文件永远不会关闭。 Use File.binread(file_name) 使用File.binread(file_name)

My initial code was written to show that binary mode needed to be used, and used open because it's "more traditional", but forgot to use the block mode. 我的初始代码是为了表明需要使用二进制模式而编写的,并且因为它“更传统”而使用open ,但忘记使用块模式。 I modified my sample code to fix that problem. 我修改了我的示例代码以解决该问题。

However, the file would be closed implicitly by Ruby as the interpreter shuts down when the script ends, as part of housekeeping that occurs. 但是,由于解释器在脚本结束时关闭,因此该文件将由Ruby隐式关闭,这是发生内务管理的一部分。 However, it's better to explicitly close the file. 但是,最好明确close文件。 If the OP is using RubyZip like I think, that will automatically happen if a block is passed to open . 如果OP像我想的那样使用RubyZip ,那么如果将块传递给open ,则会自动发生。 Otherwise, read and readbin will both read to EOF and close the file. 否则, readreadbin都将读取到EOF并关闭文件。 Code using those methods needs to be sensitive to the need to read blocks if the input file is an unknown size or larger than available buffer space. 如果输入文件的大小未知或大于可用缓冲区空间,则使用这些方法的代码需要对读取块的需求敏感。

I had a similar problem when I was reading Lib files. 我在阅读Lib文件时遇到了类似的问题。 Here's my solution: 这是我的解决方案:

 File.open(path + '\Wall.Lib')

Where the path corresponded to a javascript file that inputs filenames. 其中路径对应于输入文件名的javascript文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM