調査した結果、特に何もしなくてもアクセスできるようだった。
Windows の場合 CreateFile API を通じてさらにパスのプリフィクスに \?\ をつける(「\?\C:\Windows\test.txt」みたいに)必要があるが、Go/Java だと内部でやってくれる模様。
まずは Go の場合のテスト
main.go
package main
import (
"fmt"
"io/ioutil"
"os"
"github.com/blono/win" // Fork of lxn/win see https://qiita.com/manymanyuni/items/c41f5bf0fd141e299336
)
func main() {
longPath := `C:\Users\manymanyuni\Desktop\long\loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\loooooooooooooooooooooooooooooong.txt`
file := win.CreateFile(`\\?\`+longPath, win.GENERIC_ALL, 0, nil, win.CREATE_ALWAYS, win.FILE_ATTRIBUTE_NORMAL, win.HANDLE(unsafe.Pointer(nil)))
var c uint32 = 8
win.WriteFile(file, uintptr(unsafe.Pointer(winut.NewUTF16("test"))), c, &c, nil)
win.CloseHandle(file)
bytes, err := ioutil.ReadFile(longPath) // OK!
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(string(bytes))
bytes, err = ioutil.ReadFile(`\\?\` + longPath) // OK!
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(string(bytes))
}
ちなみに、ioutil.ReadFile に渡すパスを「\?\」で始めても動いたので、Go の Windows 実装は見てないが恐らくこのあたりのプリフィクスを考慮しながら CreateFileW をたたいているのだと思われる。
さらに、Java の場合のテスト
Test.java
import java.io.FileReader;
import java.io.IOException;
public class Test {
public static void main(String args[]) throws IOException {
var path = "C:\\Users\\manymanyuni\\Desktop\\long\\loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\\loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\\loooooooooooooooooooooooooooooong.txt";
try (var reader = new FileReader(path)) {
System.out.println(reader.read());
}
}
}
使った Java のバージョンはこちら
openjdk version "11.0.3" 2019-04-16 LTS
OpenJDK Runtime Environment Corretto-11.0.3.7.1 (build 11.0.3+7-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.3.7.1 (build 11.0.3+7-LTS, mixed mode)