Ruby
、 C#
、 Go
の標準添付ライブラリで file:///c:\temp\doc.txt
のようなパスを生成・パースした時の違いを示します。Ruby
だけは標準ライブラリの仕様上少し手を加えてあげないと動きませんでした。そのあたり少しフェアじゃないかもしれません。
参考サイト
C#
using System; namespace ConsoleApp22 { class Program { static void GenUrl(string winPath) { Uri u = new Uri(winPath); Console.WriteLine(u.AbsoluteUri); } static void GenPath(string urlPath) { Uri u = new Uri(urlPath); string winPath = u.LocalPath + Uri.UnescapeDataString(u.Fragment); Console.WriteLine(winPath); } static void Main(string[] args) { GenUrl(@"c:\temp\テスト doc#1.txt"); // file:///c:/temp/%E3%83%86%E3%82%B9%E3%83%88%20doc%231.txt GenPath(@"file:///c:\temp\テスト doc#1.txt"); // c:\temp\テスト doc#1.txt } } }
Go
package main import ( "fmt" "net/url" ) func GenUrl(winPath string) { u := &url.URL{} u.Scheme = "file" u.Path = winPath fmt.Println(u.String()) } func GenPath(urlPath string) { u, _ := url.Parse(urlPath) fmt.Println(u.Path + "#" + u.Fragment) } func main() { GenUrl("c:\\temp\\テスト doc#1.txt") // file://c:%5Ctemp%5C%E3%83%86%E3%82%B9%E3%83%88%20doc%231.txt GenPath("file:///c:\\temp\\テスト doc#1.txt") // /c:\temp\テスト doc#1.txt }
Ruby
require 'URI' def escape_path(path) path.gsub(/\\/, "\/").split("/").map { |elem| URI.encode_www_form_component(elem) }.join("/") end def gen_url(win_path) uri = URI::Generic.build({ scheme: "file", path: escape_path("/#{win_path}") }) puts uri.to_s end def gen_path(url_path) uri = URI.parse(escape_path(url_path.gsub(/^file:\/\/\//, ""))) puts uri.path end def decode_gen_path(url_path) uri = URI.parse(escape_path(url_path.gsub(/^file:\/\/\//, ""))) puts URI.decode_www_form_component(uri.path) end gen_url(%q|c:\temp\テスト doc#1.txt|) # file:///c%3A/temp/%E3%83%86%E3%82%B9%E3%83%88+doc%231.txt gen_path(%q|file:///c:\\temp\\テスト doc#1.txt|) # c%3A/temp/%E3%83%86%E3%82%B9%E3%83%88+doc%231.txt decode_gen_path(%q|file:///c:\\temp\\テスト doc#1.txt|) # c:/temp/テスト doc#1.txt
結果
- file:/// スキーマの生成
言語 | 生成されたパス |
---|---|
C# | file:///c:/temp/%E3%83%86%E3%82%B9%E3%83%88%20doc%231.txt |
Go | file://c:%5Ctemp%5C%E3%83%86%E3%82%B9%E3%83%88%20doc%231.txt |
Ruby | file:///c%3A/temp/%E3%83%86%E3%82%B9%E3%83%88+doc%231.txt |
- file:/// スキーマのパース
言語 | パースされたパス |
---|---|
C# | c:\temp\テスト doc#1.txt |
Go | /c:\temp\テスト doc#1.txt |
Ruby(デコードなし) | c%3A/temp/%E3%83%86%E3%82%B9%E3%83%88+doc%231.txt |
Ruby(デコードあり) | c:/temp/テスト doc#1.txt |
やはり C# はすごいきれいに作れる印象があります。
Go は C# 同様に平易に生成・パースができました。ただ、パースした際に頭に /
がついてくるので実際にファイルパスとして使用するときは一工夫が必要そうです。
Ruby は Windowsはあまり得意ではないプラットフォームであることから自然には生成・パースはできませんでした。生成・パースには工夫が必要でした。ただ、Rubyは addressable
という gem によって簡単に生成・パースできるようになるため、そこまで問題ではないと思いました。
おまけ
addressable
を使用した Ruby の例を以下に示します。
require 'addressable/uri' def gen_url(win_path) uri = Addressable::URI.convert_path(win_path) puts uri.to_s end def gen_path(url_path) uri = Addressable::URI.parse(url_path) puts uri.path end gen_url(%q|c:\temp\テスト doc#1.txt|) # file:///c:/temp/%E3%83%86%E3%82%B9%E3%83%88%20doc#1.txt gen_path(%q|file:///c:\\temp\\テスト doc#1.txt|) # /c:\temp\テスト doc