<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                12-I/O ====== [I/O模塊](#121-io%E6%A8%A1%E5%9D%97) [文件模塊](#122-%E6%96%87%E4%BB%B6%E6%A8%A1%E5%9D%97) [路徑模塊](#123-%E8%B7%AF%E5%BE%84%E6%A8%A1%E5%9D%97) [進程和組長](#124-%E8%BF%9B%E7%A8%8B%E5%92%8C%E7%BB%84%E9%95%BF) [*iodata*和*chardata*](#125-iodata%E5%92%8Cchardata) 本章簡單介紹Elixir的輸入、輸出機制以及相關的模塊, 如[IO](http://elixir-lang.org/docs/stable/elixir/IO.html), [文件](http://elixir-lang.org/docs/stable/elixir/File.html) 和[路徑](http://elixir-lang.org/docs/stable/elixir/Path.html)。 現在介紹I/O似乎有點早,但是I/O系統可以讓我們一窺Elixir哲學,滿足我們對該語言以及VM的好奇心。 ##12.1-IO模塊 IO模塊是Elixir語言中讀寫標準輸入、輸出、標準錯誤、文件、設備的主要機制。 使用該模塊的方法頗為直接: ```elixir iex> IO.puts "hello world" "hello world" :ok iex> IO.gets "yes or no? " yes or no? yes "yes\n" ``` IO模塊中的函數默認使用標準輸入輸出。 我們也可以傳遞```:stderr```來指示將錯誤信息寫到標準錯誤設備上: ```elixir iex> IO.puts :stderr, "hello world" "hello world" :ok ``` #12.2-文件模塊 文件模塊包含了可以讓我們讀寫文件的函數。 默認情況下文件是以二進制模式打開,它要求程序員使用特殊的```IO.binread/2``` 和```IO.binwrite/2```函數來讀寫文件: ```elixir iex> {:ok, file} = File.open "hello", [:write] {:ok, #PID<0.47.0>} iex> IO.binwrite file, "world" :ok iex> File.close file :ok iex> File.read "hello" {:ok, "world"} ``` 文件可以使用```:utf8```編碼打開,然后就可以被IO模塊中其他函數使用了: ```elixir iex> {:ok, file} = File.open "another", [:write, :utf8] {:ok, #PID<0.48.0>} ``` 除了打開、讀寫文件的函數,文件模塊還有許多函數來操作文件系統。 這些函數根據Unix功能相對應的命令命名。 如```File.rm/1```用來刪除文件;```File.mkdir/1``` 用來創建目錄;```File.mkdir_p/1```創建目錄并保證其父目錄一并創建; 還有```File.cp_r/2```和```File.rm_rf/2```用來遞歸地復制和刪除整個目錄。 你還會注意到文件模塊中,一般函數都有一個名稱類似的版本。區別是名稱上一個有!(bang)一個沒有。 例如,上面的例子我們在讀取“hello”文件時,用的是不帶!號的版本。 下面用例子演示下它們的區別: ```elixir iex> File.read "hello" {:ok, "world"} iex> File.read! "hello" "world" iex> File.read "unknown" {:error, :enoent} iex> File.read! "unknown" ** (File.Error) could not read file unknown: no such file or directory ``` 注意看,當文件不存在時,帶!號的版本會報錯。就是說不帶!號的版本能照顧到模式匹配出來的不同情況。 但有的時候,你就是希望文件在那兒,!使得它能報出有意義的錯誤。 因此,不要寫: ```elixir {:ok, body} = File.read(file) ``` 相反地,應該這么寫: ```elixir case File.read(file) do {:ok, body} -> # handle ok {:error, r} -> # handle error end ``` 或者 ```elixir File.read!(file) ``` ## 12.3-路徑模塊 文件模塊中絕大多數函數都以路徑作為參數。通常這些路徑都是二進制,可以被路徑模塊提供的函數操作: ```elixir iex> Path.join("foo", "bar") "foo/bar" iex> Path.expand("~/hello") "/Users/jose/hello" ``` 有了以上介紹的幾個模塊和函數,我們已經能對文件系統進行基本的IO操作。 下面將討論I/O模塊中令人好奇的高級話題。這部分不是寫Elixir程序必須掌握的,可以跳過不看。 但是如果你大概地瀏覽一下,可以了解IO是如何在VM上實現以及其它一些有趣的內容。 ## 12.4-進程和組長 你可能已經發現,```File.open/2```函數返回了一個包含PID的元祖: ```elixir iex> {:ok, file} = File.open "hello", [:write] {:ok, #PID<0.47.0>} ``` I/O模塊實際上是同進程協同工作的。當你調用```IO.write(pid, binary)```時, I/O模塊將發送一條消息給執行操作的進程。 讓我們用自己的代碼表述下這個過程: ```elixir iex> pid = spawn fn -> ...> receive do: (msg -> IO.inspect msg) ...> end #PID<0.57.0> iex> IO.write(pid, "hello") {:io_request, #PID<0.41.0>, #PID<0.57.0>, {:put_chars, :unicode, "hello"}} ** (ErlangError) erlang error: :terminated ``` 調用```IO.write/2```之后,可以看見打印出了發給IO模塊的請求。 然而因為我們沒有提供某些東西,這個請求失敗了。 [StringIO模塊](http://elixir-lang.org/docs/stable/elixir/StringIO.html) 提供了一個基于字符串的IO實現: ```elixir iex> {:ok, pid} = StringIO.open("hello") {:ok, #PID<0.43.0>} iex> IO.read(pid, 2) "he" ``` Erlang虛擬機用進程給I/O設備建模,允許同一個網絡中的不同節點通過交換文件進程, 實現節點間的文件讀寫。在所有IO設備之中,有一個特殊的進程,稱作組長(group leader)。 當你寫東西到標準輸出,實際上是發送了一條消息給組長,它把內容寫給*STDIO文件表述者*: ```elixir iex> IO.puts :stdio, "hello" hello :ok iex> IO.puts Process.group_leader, "hello" hello :ok ``` 組長可為每個進程做相應配置,用于處理不同的情況。 例如,當在遠程終端執行代碼時,它能保證遠程機器的消息可以被重定向到發起操作的終端上。 ## 12.5-*iodata*和*chardata* 在以上所有例子中,我們都用的是二進制/字符串方式讀寫文件。 在“二進制、字符串和字符列表”那章里,我們注意到字符串就是普通的bytes, 而字符列表是code points(字符碼)的列表。 I/O模塊和文件模塊中的函數接受列表作為參數。 還可以接受混合類型的列表,里面內容是整形、二進制都行: ```elixir iex> IO.puts 'hello world' hello world :ok iex> IO.puts ['hello', ?\s, "world"] hello world :ok ``` 盡管如此,有些地方還是要注意。一個列表可能表示一串byte,或者一串字符。 用哪一種需要看I/O設備是怎么編碼的。 如果不指明編碼,文件就以raw模式打開,這時候只能用文件模塊里bin*開頭(二進制版) 的函數對其進行操作。 這些函數接受*iodata*作為參數,即,它們期待一個整數值的列表,用來表示byte或二進制。 盡管只是細微的差別,如果你打算傳遞列表給那些函數,你需要考慮那些細節。 底層的bytes可以表示二進制,這種表示就是raw的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看