Elixir学习笔记——输入输出和文件系统

本章介绍输入/输出机制、文件系统相关任务以及相关模块(如 IO、File 和 Path)。IO 系统提供了一个很好的机会来阐明 Elixir 和 Erlang VM 的一些思维模式和新奇思想。

输入输出模块

输入输出模块是 Elixir 中读写标准输入/输出 (:stdio)、标准错误 (:stderr)、文件和其他输入输出设备的主要机制。该模块的使用非常简单:

默认情况下,输入输出模块中的函数从标准输入读取并写入标准输出。我们可以通过传递 :stderr 作为参数(以便写入标准错误设备)来更改此设置:

文件模块

文件模块包含允许我们将文件作为输入输出设备打开的函数。默认情况下,文件以二进制模式打开,这要求开发人员使用输入输出模块中的特定 IO.binread/2 和 IO.binwrite/2 函数:

潜在数据丢失警告
以下代码打开一个文件进行写入。如果给定路径上有现有文件,则将删除其内容。

可以使用 :append 选项而不是 :write 打开文件以保留其内容。您还可以传递 :utf8 选项,该选项告诉 File 模块将从文件读取的字节解释为 UTF-8 编码的字节。

除了用于打开、读取和写入文件的函数外,File 模块还有许多用于文件系统的函数。这些函数以它们的 UNIX 等效函数命名。例如,File.rm/1 可用于删除文件,File.mkdir/1 可用于创建目录,File.mkdir_p/1 可用于创建目录及其所有父链。甚至还有 File.cp_r/2 和 File.rm_rf/1 分别用于递归复制和删除文件和目录(即,也复制和删除目录的内容)。

您还会注意到 File 模块中的函数有两种变体:一种是“常规”变体,另一种是带有尾随感叹号 (!) 的变体。例如,当我们读取上面示例中的“hello”文件时,我们使用 File.read/1。或者,我们可以使用 File.read!/1:

请注意,带有 ! 的版本返回文件的内容而不是元组,如果出现任何问题,该函数会引发错误。

没有 ! 的版本当您想使用模式匹配处理不同的结果时,是首选:

但是,如果您希望文件在那里,则感叹号变体更有用,因为它会引发有意义的错误消息。避免写:

因为,如果发生错误,File.read/1 将返回 {:error,reason},并且模式匹配将失败。您仍将获得所需的结果(引发错误),但消息将与不匹配的模式有关(因此对于错误的具体含义却一无所知)。

因此,如果您不想处理错误结果,请优先使用以感叹号结尾的函数,例如 File.read!/1。

路径模块

文件模块中的大多数函数都要求将路径作为参数。最常见的是,这些路径将是常规二进制文件。路径模块提供了处理此类路径的功能:

最好使用路径模块中的函数,而不是直接操作字符串,因为路径模块可以透明地处理不同的操作系统。最后,请记住,在 Windows 上执行文件操作时,Elixir 会自动将斜杠 (/) 转换为反斜杠 (\)。

至此,我们介绍了 Elixir 提供的用于处理输入输出和与文件系统交互的主要模块。在下一节中,我们将深入了解一下,并了解输入输出系统如何在 VM 中实现。

进程

您可能已经注意到 File.open/2 返回一个类似 {:ok, pid} 的元组:

发生这种情况是因为输入输出模块实际上与进程一起工作(请参阅上一章)。假设文件是​​一个进程,当您写入已关闭的文件时,实际上是在向已终止的进程发送一条消息:

让我们更详细地了解当您请求 IO.write(pid, binary) 时会发生什么。输入输出模块向 pid 标识的进程发送一条消息,其中包含所需的操作。一个小的临时进程可以帮助我们看到它:

在 IO.write/2 之后,我们可以看到打印出来的输入输出模块发送的请求(一个四元素元组)。不久之后,我们看到它失败了,因为输入输出模块期望某种结果,而我们没有提供。

通过使用进程对输入输出设备进行建模,Erlang VM 甚至允许我们跨节点读取和写入文件。太棒了!

iodata 和 chardata

在上面的所有示例中,我们在写入文件时都使用了二进制文件。但是,Elixir 中的大多数 IO 函数也接受“iodata”或“chardata”。

使用“iodata”和“chardata”的主要原因之一是性能。例如,假设您需要在应用程序中向某人打招呼:

由于 Elixir 中的字符串是不可变的,与大多数数据结构一样,上面的示例会将字符串“Mary”复制到新的“Hello Mary!”字符串中。虽然这对于上面的短字符串来说不太可能,但对于大字符串来说,复制可能非常昂贵!因此,Elixir 中的 IO 函数允许您传递字符串列表:

在上面的示例中,没有复制。相反,我们创建一个包含原始名称的列表。我们将此类列表称为“iodata”或“chardata”,我们很快就会了解它们之间的确切区别。

这些列表非常有用,因为它实际上可以在几种情况下简化字符串的处理。例如,假设您有一个值列表,例如 [“apple”、“banana”、“lemon”],您希望用逗号分隔这些值写入磁盘。您如何实现这一点?

一种方式是使用 Enum.join/2 并将值转换为字符串:

以上通过将每个值复制到新字符串中来返回一个新字符串。但是,有了本节中的知识,我们知道我们可以将字符串列表传递给 IO/File 函数。因此我们可以这样做:

"iodata" 和 "chardata" 不仅包含字符串,还可能包含任意嵌套的字符串列表:

"iodata" 和 "chardata" 也可能包含整数。例如,我们可以使用 ? 作为分隔符来打印以逗号分隔的值列表,该分隔符表示逗号 (44):

"iodata" 和 "chardata" 之间的区别正是所述整数所代表的内容。对于 iodata,整数表示字节。对于 chardata,整数表示 Unicode 码位。对于 ASCII 字符,字节表示与码位表示相同,因此它适合这两种分类。但是,默认 IO 设备与 chardata 一起工作,这意味着我们可以这样做:

总体而言,列表中的整数可能表示一堆字节或一堆字符,使用哪一个取决于 IO 设备的编码。如果文件未经过编码打开,则文件应处于原始模式,并且必须使用 IO 模块中以 bin* 开头的函数。这些函数需要 iodata 作为参数,其中列表中的整数表示字节。

另一方面,默认 IO 设备 (:stdio) 和使用 :utf8 编码打开的文件与 IO 模块中的其余函数一起工作。这些函数需要 chardata 作为参数,其中整数表示码位。

虽然这是一个微妙的差异,但如果您打算将包含整数的列表传递给这些函数,则只需担心这些细节。如果您传递二进制文件或二进制文件列表,则不会出现歧义。

最后,还有最后一个构造称为 charlist,我们在前面的章节中讨论过。Charlist 是 chardata 的一个特例,其中所有值都是表示 Unicode 码位的整数。它们可以用 ~c 符号创建:

字符列表主要出现在与 Erlang 交互时,因为一些 Erlang API 使用字符列表作为字符串的表示。因此,任何包含可打印 ASCII 码位的列表都将打印为字符列表:

我们在这个小部分中塞进了很多内容,让我们来整理一下:

1.iodata 和 chardata 是二进制和整数的列表。这些二进制和整数可以任意嵌套在列表中。它们的目标是在使用 IO 设备和文件时提供灵活性和性能;

2.iodata 和 chardata 之间的选择取决于 IO 设备的编码。如果文件在没有编码的情况下打开,则文件需要 iodata,并且必须使用以 bin* 开头的 IO 模块中的函数。默认 IO 设备 (:stdio) 和使用 :utf8 编码打开的文件需要 chardata,并与 IO 模块中的其余函数配合使用;

3.charlists 是 chardata 的一个特例,它专门使用整数 Unicode 代码点列表。它们可以使用 ~c 符号创建。如果列表中的所有整数都代表可打印的 ASCII 代码点,则使用 ~c 符号自动打印整数列表。

这结束了我们对 IO 设备和 IO 相关功能的介绍。我们了解了三个 Elixir 模块 - IO、File 和 Path - 以及 VM 如何使用进程来实现底层 IO 机制以及如何使用 chardata 和 iodata 进行 IO 操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/27807.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue学习(一)

1.vue是用于构建用户界面的渐进式js框架,自底向上逐层的应用: 简单应用:只需一个轻量小巧的核心库; 复杂应用:可以引入各式各样的vue插件; 2.vue特点: 采用组件化模式,提高代码复…

Python中关于电商商品数据的采集【taobao/JD/商品详情数据返回】

在Python中采集电商商品数据(如淘宝、京东等)通常涉及到网络爬虫(web scraping)或称为网络数据抓取(web data scraping)。由于电商平台通常会有反爬虫机制,因此直接抓取数据可能会遇到各种挑战&…

基于51单片机的智能水表

一.硬件方案 本设计主要以51单片机作为主控处理器的智能水表,该水表能够记录总的用水量和单次用水量,当用水量超出设定值时系统发出声光报警提醒,水量报警值能够通过按键进行自行设置,并且存储于AT24C02中,并且可以测…

C++11默认成员函数控制

默认成员函数有 如果自己不显示声明,那么默认编译器会自己生成一个 如果有一个构造函数被声明了,那其他的默认函数编译器就不会再生成 这样的有时又不生成,容易造成混乱,于是C11让程序员可以控制是否需要编译器生成。 显式缺省函…

H5112B 降压恒流芯片12V24V36V48V60V72V100V 1.2ALED 调光无频闪光滑细腻

H5112B多功能LED恒流驱动器是一款具有良好性能与高度集成度的驱动芯片。以下是该产品的主要优点及应用领域的详细分析: 产品优点: 宽电压输入范围:H5112B支持5V至90V的宽电压输入范围,使其能够适应多种不同的电源环境&#xff0…

(虚拟机)VMware软件的安装及Ubuntu系统安装

一、VMware软件的安装 软件下载,可以自己找或者百度网盘下载: 通过百度网盘分享的文件:ubuntu16…等2个文件 链接:https://pan.baidu.com/s/1VEnZKY9DJ1T1vC3ae20gKQ 提取码:11b6 复制这段内容打开「百度网盘APP 即可获取」 1、解压VMwar…

本地生活元宇宙 橘子浑身都是宝,吃对营养加倍

橘子是秋冬季节的应季水果 含有丰富的营养价值 而且浑身都是宝 但你知道吗 吃橘子也是有讲究的 如何吃橘子才能营养最大化? 橘子有哪些食用禁忌? 一起来看看吧~ 划重点 一颗橘子,3大营养 橘子具有开胃理气、止渴润肺、治胸膈结气、…

06--jenkins构建CI_CD

前言:上一篇文章整理了git的部署和使用,这章主要复习持续集成软件Jenkins,这个技术现在在云计算方面也是有应用的,同时也是越高级越智能的软件代表。 1、概念简介 1)jenkins是什么 Jenkins是一个开源的、可扩展的持…

Linux 终端窗口设置为透明

Linux 终端窗口设置为透明 打开终端 右键鼠标 选择Profile Preferences 点击Background 选择 Transparent background 拖动滑条调整透明度 完成。

Nintex流程平台引入生成式人工智能,实现自动化革新

工作流自动化提供商Nintex宣布在其Nintex流程平台上推出一系列新的人工智能驱动改进。这些增强显著减少了文档化、管理和自动化业务流程所需的时间。这些新特性为Nintex流程平台不断扩展的人工智能能力增添了新的亮点。 Nintex首席产品官Niranjan Vijayaragavan表示&#xff1a…

甄嬛传熹贵妃上户口:如果让他陪你过冬天,那朕能不能睡中间?贝叶斯模型推导爸爸去哪儿

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 背景 《甄嬛传》是大家耳熟能详的宫廷剧,其中复杂的宫斗情节和深刻的人物刻画让人津津乐道。甄嬛因为与皇帝(四郎)闹翻了,去甘露寺待了一段时间&#x…

Navicat和SQLynx产品功能比较一(整体比较)

Navicat和SQLynx都是数据库管理工具,在过去的二十年中,国内用户主要是使用Navicat偏多,一般是个人简单开发需要,数据量一般不大,开发相对简单。SQLynx是最近几年的数据库管理工具,Web开发,桌面版…

PyTorch C++扩展用于AMD GPU

PyTorch C Extension on AMD GPU — ROCm Blogs 本文演示了如何使用PyTorch C扩展,并通过示例讨论了它相对于常规PyTorch模块的优势。实验在AMD GPU和ROCm 5.7.0软件上进行。有关支持的GPU和操作系统的更多信息,请参阅系统要求(Linux&#xf…

代码安全问题0

该篇目主要是记录日常遇到的代码安全问题的记录 # 清空会话的RAM del combined_list gc.collect()# 重新读取上述合成的NPZ文件为一个新的文件 combined_arrays [] for i in range(1, batch_count 1): # 从1到batch_count1,包括剩余的最后一个文件data np.load(…

SpringBoot使用jasypt实现数据库信息的脱敏,以此来保护数据库的用户名username和密码password(容易上手,详细)

1.为什么要有这个需求? 一般当我们自己练习的时候,username和password直接是爆露出来的 假如别人路过你旁边时看到了你的数据库账号密码,他跑到他的电脑打开navicat直接就是一顿连接,直接疯狂删除你的数据库,那可就废…

字符数组基础知识及题目

死识。。。 字符该如何存储呢?这一点我们在以前就接触过了。用char来存储。 如何输入一个单词呢? char a[10002]; scanf("%s",a); 就不用地址符了。 如何输入句子呢? char a[100002]; gets(a); gets是读入句子的&#xff0c…

从0开发一个Chrome插件:高级功能开发——存储数据

前言 这是《从0开发一个Chrome插件》系列的第十六篇文章,本系列教你如何从0去开发一个Chrome插件,每篇文章都会好好打磨,写清楚我在开发过程遇到的问题,还有开发经验和技巧。 专栏: 从0开发一个Chrome插件:什么是Chrome插件?从0开发一个Chrome插件:开发Chrome插件的必…

【第7章】Vue之第一个Vue程序(Vue创建)

文章目录 前言一、创建1. 命令行2. 创建3. 安装依赖 二、启动三、访问总结 前言 接下来我们通过VSCode来创建我们的第一个Vue应用程序。 一、创建 1. 命令行 Terminal>New Terminal 2. 创建 #这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工…

中介子方程十六

X$XFX$XEXyXαXiX$XαXiXrXkXtXyX$XpXVX$XdXuXWXtXWXuXdX$XVXpX$XyXtXkXrXiXαX$XiXαXyXEX$XFX$XEXyXαXiX$XαXiXrXkXtXyX$XpXVX$XdXuXWXtXWXuXdX$XVXpX$XyXtXkXrXiXαX$XiXαXyXEX$XαXηXtXαX$XWXyX$XyXWX$XpXαXqXηX$XeXαXhX$XdX$XpX$XdX$XyXeXαX$XEXyXαXiX$XαXiXrX…

如何使用Python中的type()函数和isinstance()函数

在Python中,type()函数和isinstance()函数都用于确定一个对象的类型,但它们在用法和目的上有所不同。 1. type()函数 type()函数返回对象的数据类型(或类)。它接受一个参数(即要检查的对象),并…