ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Ruby 文件读写与序列化实战:从 File/IO 基础到 JSON、YAML 与状态持久化

Ruby 文件读写与序列化实战:从 File/IO 基础到 JSON、YAML 与状态持久化 Ruby 文件读写与序列化实战从 File/IO 基础到 JSON、YAML 与状态持久化【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum本篇技术指南围绕 Odin 课程 Ruby 路径中的文件读写与序列化主题展开系统讲解如何在 Ruby 脚本中通过File、IO、Dir类读写硬盘数据理解文件即字节流的核心模型并掌握 JSON 与 YAML 两种主流序列化格式的互转方法。学完本篇你将能够把 Ruby 对象保存为可存储、可传输的字符串格式并在命令行项目中实现存档/读档这类典型的状态持久化功能。一、核心认知文件就是自上而下的字节流在之前的练习中你编写的多是自包含的命令行程序。现在需要开始与文件打交道文件本质上是一组比特与字节的集合你需要在程序中打开它、读入内存、修改并重新保存。虽然很多文件例如图片在文本编辑器中打开时像一堆杂乱无章的数据但一个非常有帮助的思维模型是把所有文件都看作一条极长的字符串stream of bytes你的脚本自上而下地读取它们并在读取过程中执行你指定的各种操作。# 文件在 Ruby 中的本质一个可迭代的字节/行流 File.foreach(example.txt) do |line| puts line # 自上而下逐行处理 end幸运的是Ruby 在处理文件方面提供了相当便利的工具它能够把这串字节读入程序并让你用已经熟悉的 Ruby 对象字符串、数组、哈希来操作它们。只要记住文件就是从顶部读到底部的一长串单词/字符/字节整个模型就会非常直观。如果你想做更精细的操作——例如写入文件中某个具体位置——则需要先搞清楚当前所处的位置文件指针因为你可能正处在文件的中间某处。二、文件的两种读取方式一次读入 vs 逐行迭代本节内容对应原文档的 Lesson overview 中的第一个问题两种把硬盘上的文件存入 Ruby 脚本字符串或数组的方式。2.1 一次性读入File.read最直接的方式是用File.read把整个文件内容一次性读入一个字符串content File.read(dictionary.txt) # apple\nbanana\ncherry\n...2.2 按行读入数组File.readlines如果希望立刻得到一个按行分割的数组使用File.readlineslines File.readlines(dictionary.txt) # [apple\n, banana\n, cherry\n, ...]2.3 流式逐行处理File.foreach与 IO 对象当文件较大时一次性读入会占用较多内存。此时可以用File.foreach逐行迭代或用File.open配合代码块获得一个IO对象逐行处理File.foreach(dictionary.txt) do |line| line line.chomp # 去掉末尾换行符 puts line if line.length.between?(5, 12) end # 或者显式打开 IO 对象 File.open(dictionary.txt, r) do |file| file.each_line { |line| puts line } end原文档的 Knowledge check 中特别强调了一个问题如何通过IO对象逐行遍历文件——答案正是上面这种File.openeach_line或foreach的组合它把文件句柄抽象成可迭代的行流。三、文件信息查询与目录操作File与Dir类原文档的 Assignment 中指定阅读 Zetcode Ruby 教程中关于File和Dir类的章节其核心操作如下。3.1 判断文件/目录是否存在File.exist?(save_game.yaml) # true / false File.file?(dictionary.txt) # 是否为普通文件 Dir.exist?(saves) # 目录是否存在3.2 列出目录内容为数组Dir.entries(saves) # [., .., game_1.yaml, game_2.yaml] Dir.children(saves) # [game_1.yaml, game_2.yaml]不含 . 与 ..Dir.children返回不包含.和..的条目数组正是 Knowledge check 中如何以数组形式列出目录内容的标准答案也常被用于列出所有存档文件供玩家选择的场景。3.3 写入与创建目录# 覆盖写入w 模式会清空原文件 File.write(output.txt, hello\nworld\n) # 以追加模式打开 File.open(log.txt, a) { |f| f.puts new line } # 创建目录除非已存在 Dir.mkdir(saves) unless Dir.exist?(saves)四、序列化把数据变成可存储的字符串文件操作会把你带入序列化serialization的概念。序列化本质上就是把数据转换成可存储的格式——例如字符串。这个概念在两种场景下都非常关键本地持久化比如你正在玩一个游戏想把自己的对象和类的当前状态分数、棋盘、角色属性保存到文件中下次启动时恢复网络传输把同样的对象传送给 Web 浏览器——因为 HTTP 协议中信息只能以字符串形式传输。从原文档的 Lesson overview 中可以提炼出序列化带来的三大收益Three things made possible or much easier by serialization状态持久化程序退出后数据依然存在下次启动可以恢复这正是 Hangman 项目存档功能的根基对象网络传输让复杂的、深层嵌套的对象如User、Game实例可以跨进程、跨机器地在 HTTP 上以字符串形式传递数据交换与解耦以通用、稳定的文本格式存储和交换数据让不同语言、不同系统之间可以互相读取。Ruby 为序列化提供了非常顺手的工具。目前业界有若干被普遍接受的序列化格式其中最常见的两个是YAML和JSON。4.1 YAML轻量级配置格式典型用途Ruby on Rails 常使用 YAML 保存配置文件例如database.yml、.rubocop.yml因为它非常轻量、直白可以在文本编辑器中轻松阅读。特性缩进敏感、人类可读性极佳适合表达嵌套的配置结构。在 Ruby 中使用yaml标准库序列化与反序列化require yaml data { name: Ada, level: 5, inventory: %w[sword shield] } # Ruby 对象 - YAML 字符串 yaml_str data.to_yaml puts yaml_str # --- # :name: Ada # :level: 5 # :inventory: # - sword # - shield # YAML 字符串 - Ruby 对象 restored YAML.load(yaml_str) p restored # {:nameAda, :level5, :inventory[sword, shield]}YAML 在真实 Ruby 生态中的应用可以在本仓库的 linting_and_rubocop.md 中看到完整示例——.rubocop.yml正是用 YAML 表达 RuboCop 规则配置# 这是 .rubocop.yml 的片段 AllCops: NewCops: enable plugins: - rubocop-performance这段配置展示了 YAML 的典型用法用键值对和缩进嵌套来表达规则选项人可以直接读懂机器也能轻松解析。4.2 JSONWeb 世界的通用语言典型用途JSON 在整个 Web 中无处不在是从某个网站通过 API 向你的程序传递复杂/深层嵌套数据如对象的首选格式——例如你想对接 Google Maps 这样的服务。特性语法源自 JavaScript 对象字面量所有主流语言都能解析是 HTTP API 事实上的数据交换标准。Ruby 的标准库json提供双向转换require json # Ruby 对象 - JSON 字符串 arr [1, 2, 3] json_str arr.to_json puts json_str # [1,2,3] # JSON 字符串 - Ruby 对象 restored JSON.parse(json_str) p restored # [1, 2, 3]针对原文档 Knowledge check 中的问题如何把数组[1,2,3]序列化成 JSON 字符串格式答案就是[1,2,3].to_json。在 Rails 生态中to_json的身影更为常见。本仓库的 apis_and_building_your_own.md 详细说明了它的工作机理#to_json做两件事——先运行#as_json得到需要渲染为 JSON 的属性哈希然后用ActiveSupport::json.encode真正完成 JSON 渲染。也就是说在 Rails 里想自定义 API 返回字段时你应该覆写#as_json而不是#to_json通过调整返回的属性哈希来间接改变 JSON 输出——这也印证了JSON 是对象网络传输的载体这一论断。4.3 格式对比YAML vs JSON vs MessagePack原文档的 Knowledge check 要求思考不同序列化格式的收益对比格式可读性体积/性能典型场景YAML极佳缩进嵌套清晰较大解析较慢本地配置文件Rails 配置、RuboCop 规则JSON良好通用较小解析快Web API 数据交换、跨语言传输MessagePack差二进制极小、极快追求性能与带宽的二进制场景选择原则可以概括为人读为主选 YAML机器交换选 JSON性能优先考虑 MessagePack。五、对象级序列化保存的不只是数据而是状态原文档 Assignment 中引用了 Alan Skorkin 关于 Ruby 面向对象序列化的文章核心思想是序列化不仅适用于数组、哈希等简单结构还能把自定义类的实例连同其内部状态一起保存——这正是在游戏中途保存对象的基础。以本仓库的 project_hangman.md 为例它明确要求实现这样的功能在任何回合开始时除了猜字母玩家还应该可以选择保存游戏。记住你学过的关于序列化对象的知识。对应的技术方案是把整个游戏状态秘密单词、已猜字母、剩余猜错次数等封装进一个对象再对该对象整体序列化require yaml class HangmanGame attr_accessor :secret_word, :correct_guesses, :wrong_guesses, :remaining_attempts def initialize(secret_word) secret_word secret_word correct_guesses [] wrong_guesses [] remaining_attempts 6 end # 保存把对象序列化为 YAML 写入文件 def save(filename save_game.yaml) File.write(filename, YAML.dump(self)) end # 读档从文件读取 YAML 并还原对象 def self.load(filename save_game.yaml) YAML.load(File.read(filename)) end end game HangmanGame.new(programming) game.wrong_guesses x game.save restored HangmanGame.load p restored.secret_word # programming p restored.wrong_guesses # [x]这里的核心要点是YAML.dump(self)会把实例变量的完整状态序列化为字符串而YAML.load则根据 YAML 中记录的类信息把字符串还原为HangmanGame对象——程序重启后正好跳回你保存时的位置原项目文档原话should jump you exactly back to where you were when you saved。六、存档系统的完整实现思路把知识串起来结合 project_hangman.md 的完整要求可以看到文件读写与序列化如何在真实项目中协同工作读取外部数据程序启动时用File.readlines读入google-10000-english-no-swears.txt词典文件随机挑选一个长度在 512 之间的单词作为秘密单词状态展示维护正确/错误猜测列表显示类似_ r o g r a _ _ i n g的进度并告知剩余错误次数存档任何回合开始前允许玩家选择保存——用YAML.dump把游戏对象写入saves/目录先Dir.mkdir确保目录存在读档程序首次加载时提供打开存档选项用Dir.children(saves)列出存档YAML.load恢复对象继续游戏。七、文件与数据库殊途同归的持久化原文档最后指出文件与序列化在诸多方面与数据库的概念和目的重叠——它们都实现了数据的状态保持与持久性maintain state and permanence。两者的关系可以这样理解文件最简单直接的持久化介质以字节流形式保存任意内容由File/IO/Dir类管理序列化格式文件内容的组织规范把结构化对象转换为 YAML/JSON 等可存储字符串数据库在文件之上的结构化存储与查询层提供索引、事务、并发控制等能力。Ruby 标准库与生态为这两种路径都提供了支持面向文件的File/Dir类处理原始字节流yaml/json标准库负责格式转换而更高阶的数据库访问则交给 ActiveRecord 等 ORM 完成。本仓库 Ruby 路径中关于 ORM 的进一步内容如 active_record_basics.md即建立在这一基础之上。八、总结与知识自检回到原文档的 Lesson overview完成本课你应该能够回答两种把硬盘文件存入字符串/数组的方式File.read字符串与File.readlines数组以及流式的File.foreach/File.openeach_line序列化带来的三件事状态持久化、对象网络传输、跨系统数据交换什么是 JSON / 什么是 YAMLJSON 是 Web 通用数据交换格式YAML 是轻量、易读的配置格式Ruby 对象转 JSONobject.to_jsonJSON 转 Ruby 对象JSON.parse(string)读写硬盘可用的类与方法File.read/write/open/foreach/exist?、Dir.exist?/mkdir/children/entries等。围绕这些能力你可以在 project_hangman.md 的实战项目中完整实践存档/读档功能若想进一步了解文件输入输出的更广泛用法如 CSV 读取、ERB 模板填充可继续研读仓库中 Event Manager 教程位于 archive/ruby/files_and_serialization/project_event_manager.md它完整演示了从 CSV 读数据、用File类处理输入输出、再通过 ERB 模板批量生成结果的真实工作流。【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表