【问题标题】:How to iterate over files in a folder and encode them to base64 to store in an array in ruby?如何遍历文件夹中的文件并将它们编码为base64以存储在ruby中的数组中?
【发布时间】:2019-12-05 09:13:54
【问题描述】:
Dir.foreach("/home/kaustubh/Downloads/resumes") do |fopen|
...d << Base64.encode64(file.read)
end

我正在 ruby​​ 终端中读取文件并尝试将整个文件编码为 base64 格式,但我的输出是一个所有值都为空的数组。

数组 d 应该以 base64 编码格式存储数组中的所有文件。

【问题讨论】:

  • 作为后续问题,我正在尝试将 base64 编码文件 HTTP 发布到 URL 中。但它显示错误414,uri太长。是否有解决方法。

标签: ruby file iteration


【解决方案1】:

您的 Ruby 代码不执行任何操作。如果将其复制并粘贴到 IRB 中,则会出现错误。

根据您所写的内容,您希望读取目录中的每个文件并将其编码为 base64,然后将 base64 存储在一个数组中。以下是你的做法:

d = []
Dir['/home/kaustubh/Downloads/resumes/*'].each do |file|
  d << Base64.encode64(File.read(file))
end

Dir['/home/kaustubh/Downloads/resumes/*'] 将返回该目录内容的路径数组。 (包括子目录,所以要小心)

然后在该数组上调用.each do |file|,并为数组中的每个file 调用File.read 将文件读入字符串对象。然后使用Base64.encode64 对字符串进行编码并将其存储在您的数组中。

【讨论】:

  • 你说,“包括子目录,所以要小心”,但在代码中尝试File.read(f),其中f 是一个目录(例如,'.' 或'. .'),这当然会引发异常!
  • ...除了我的代码没有返回。和 .. (它们不是子目录,这是我警告过的)并且给出的示例似乎表明没有子目录。如果 OP 想澄清他们的例子,他们可以,但由于他们接受了这个答案,我认为它对他们有用,如果它停止工作,他们会知道原因。
  • 是的,您的代码不会返回 '.''.'(我的错误)。使用我的答案1Dir['testdir/*'] #=&gt; ["testdir/file1", "testdir/file2", "testdir/subdir"] 中的目录结构,其中最后一个是目录。不考虑提问者,但您应该更清楚,Ruby 新手选择答案意味着,呃,不是那么多。 :-)
  • 我们现在是在猜测提问者吗?他们有一个狭窄的用例,这个答案对他们有用。 Accepting an answer 并不意味着它是涵盖所有未来访问者的所有边缘情况的最佳答案,“它只是意味着作者收到了对他们个人有用的答案。”如果他们愿意,绝对欢迎 OP 不接受它并接受另一个答案。不确定会发生这种情况,因为这个答案似乎对他们个人有用。
  • 我不是在猜测提问者。关于/home/kaustubh/Downloads/resumes 是否包含子目录的问题是沉默的。在这种情况下,我们必须假设它可能,就像@Mig 和我一样。或者,您应该陈述您的假设,即它不包含子目录。
【解决方案2】:

您的示例不完整,所以我不确定这是您所追求的,但这确实收集了 Base64 中每个文件的内容:

require 'base64'

files_glob = "/home/kaustubh/Downloads/resumes/*"

base64_array = Dir.glob(files_glob).select do |filename|
  File.file? filename
end.map do |filename|
  Base64.encode64(File.read(filename))
end

如果您的文件都以扩展名结尾,您可以避免使用select 块,并使用"/home/kaustubh/Downloads/resumes/*.txt" 代替glob

选择块仅用于排除目录。与foreach 不同,glob 似乎不包含“.”。和“..”目录。但你可能还有其他的。越具体越好。

使用glob 而不是foreach 允许您使用任何迭代器方法,例如select,更重要的是map 而不仅仅是迭代。

【讨论】:

    【解决方案3】:

    假设感兴趣的目录由变量target_dir 保存。那么我们想要:

    require 'base64'
    
    files_of_interest(target_dir).map { |f| Base64.encode64(File.read(file)) }
    

    在哪里写方法files_of_interest

    这里有一些数据(Linux)。

    ls -la testdir
    drwxr-xr-x 1 cary cary  32 Jul 27 09:22 .
    drwxr-xr-x 1 cary cary 346 Jul 27 09:22 ..
    -rw-r--r-- 1 cary cary   0 Jul 27 09:22 file1
    -rw-r--r-- 1 cary cary   0 Jul 27 09:22 file2
    drwxr-xr-x 1 cary cary  28 Jul 27 11:41 subdir
    
    ls -la testdir/subdir
    drwxr-xr-x 1 cary cary 28 Jul 27 11:41 .
    drwxr-xr-x 1 cary cary 32 Jul 27 09:22 ..
    -rw-r--r-- 1 cary cary  0 Jul 27 09:23 file3
    drwxr-xr-x 1 cary cary 10 Jul 27 11:41 subsubdir
    
    ls -la testdir/subdir/subsubdir
    drwxr-xr-x 1 cary cary 10 Jul 27 11:41 .
    drwxr-xr-x 1 cary cary 28 Jul 27 11:41 ..
    -rw-r--r-- 1 cary cary  0 Jul 27 11:41 file4
    

    案例1:构造testdir中所有非目录文件的数组

    可以使用Dir::[]Dir::globDir::foreach

    使用[]

    def files_of_interest(target_dir)
      Dir["#{target_dir}/*"].select { |f| File.file?(f) }
    end
    
    files_of_interest("testdir")
      #=> ["testdir/file1", "testdir/file2"]
    

    注意

    Dir["#{target_dir}/*"]
      #=> ["testdir/file1", "testdir/file2", "testdir/subdir"] 
    

    使用glob

    def files_of_interest(target_dir)
      Dir.glob("#{target_dir}/*").select { |f| File.file?(f) }
    end
    
    files_of_interest("testdir")
      #=> ["testdir/file1", "testdir/file2"]
    

    使用foreach

    def files_of_interest(target_dir)
      Dir.foreach(target_dir).map { |f| "#{target_dir}/#{f}" }.
          select { |f| File.file?(f) }
      end
    
    files_of_interest("testdir")
      #=> ["testdir/file1", "testdir/file2"]
    

    注意

    enum = Dir.foreach(target_dir)
      #=> #<Enumerator: Dir:foreach("testdir")> 
    enum.to_a
      #=> [".", "..", "file1", "file2", "subdir"]
    

    File::file?。请注意,我们可以将Array#select 替换为Array#reject,将File::file? 替换为File::directory?

    案例2:构造testdir中的所有文件及其嵌套的非目录子目录的数组

    这里我们必须使用Dir::glob

    def files_of_interest(target_dir)
      Dir.glob("#{target_dir}/**/*").select { |f| File.file?(f) }
    end
    
    files_of_interest("testdir")
      #=> ["testdir/file1", "testdir/file2", "testdir/subdir/file3",
      #    "testdir/subdir/subsubdir/file4"] 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-18
      • 2021-10-09
      • 2018-05-20
      • 2021-09-19
      相关资源
      最近更新 更多