質問: 現在、端末内の写真を使用するアプリを作成しています。 アプリ作成に際してのOS仕様の確認にあたり、 「Android端末において、OSでどの深さのフォルダ階層まで扱うことができるか(ファイルパスの長さの上限はいくつか)」 を調べておりますが、「上限はない」「ファイル名を含めて255文字」「ファイル名を含めて260文字」等様々な情報があり、どれが本当なのかの判断がつかない状況です。 実際にAndroid端末上で動作を確認したところ、255、260を超えても問題なく扱うことができている為、「上限はない」が正解なのかと思っています。 上記につきまして、公式に記載されているサイトなどありませんでしょうか。 ご存知の方がいらっしゃいましたらご教授いただけますと幸いです。
回答: 公式に「Androidでは最大N文字のPATH名をサポートしている」と記載してるものは無いと思われます。 「**Androidのファイルシステムは種類によって長大なPATH文字列を許すのだけれど、ファイルやPATHを取り扱うランタイムライブラリがサポートしきれていないので、実質4096バイト(場合によって文字)未満で使うこと**」と言うのが、私のこの回答の結論です。 ファイルのPATH文字数とは、この場合ファイルが存在するディレクトリ名を含んだ、ファイル名のフルPATH名を指すことと思いますが、最終的にはファイルシステムがそのディレクトリ名とファイル名を格納できるサイズが上限となります。Androidが扱うファイルシステムは ext4ファイルシステムやSDカードで使うexFAT等ですが、これらはそれぞれ、収納できるサイズが違います。 1. ext4 wikipedia - ext4 filesystem ファイル名は255バイト、サブディレクトリ数は無制限。 私自身、Linux(Ubuntu16.04)上で確認しましたが、ディレクトリ名も最大255バイトです。 2. exFAT wikipedia - exFAT ファイル名は255文字 Microsoft Docs - File System Functionality Comparison こちらの記述にはPATH長として32,760文字との記載がある ext4がファイル名とディレクトリ名がそれぞれ単独で255バイト、ディレクトリ数は制限がありませんので、理論的に考えるとディレクトリを掘り進めることでPATHの長さに制限が無くなります。外部ストレージで使われるであろうexFATは、ファイル名が255文字、PATH名は32,760文字です。尚、ext4 ではバイト単位、exFATは文字(UNICODE UTF-16)単位と言う点も注意する必要があります。 ここから話が少し複雑になりますが、実際にファイルやディレクトリを操作する為にファイルシステムにアクセスする際、AndroidアプリはAndroid Runtimeを介し、linuxのシステムコールへと行き着きます。内部の詳細は私自身も把握している訳ではありませんが、その途中でC言語ベースで作られたコードがあり、それらはPATH名の最大長として適時、ヘッダーファイル limits.h で定義される`PATH_MAX`マクロを使っているものと思われます。AndroidのOSカーネルはLinuxベースですが、そのLinux上で使う場合のlimits.hにおける`PATH_MAX`は以下のようになっていて、末端のNULL文字を入れて最大で4096バイトです。 ``` /* limits.h */ #define PATH_MAX 4096 /* 末端のNULLを含むPATH名 */ ``` ランタイムライブラリでは、ディレクトリとファイル名はそれぞれ255バイト、組み合わせて4095バイト以下のPATH長で扱われる可能性がある、ということを示唆していると思います。 実際 Nexus 6P (Android 6.0, APIレベル23)のAndroidエミュレーター上で確認してみました。アプリ用のデータディレクトリ `/data/user/0/<パッケージ名>/app_<アプリ名>...` 下にディレクトリを作成すると、4096バイト以上のPATHとなるディレクトリを作成することはできませんでした。Javaの文字はUNICODE(UTF-16)ですので、もしPATH名に例えば日本語を使ってしまうと4096文字未満にもなりえます。あくまで私の推測ですが、4096と言うのは前述したようにランタイムの制限だと思われます。 AndroidのAPI(JavaのFile API)ではカレントディレクトリを変えることはできませんので、カレントディレクトリを変更しつつ相対PATH指定でディレクトリを掘り進めることはできず、その為、実質的に取り扱えるPATH長としては4095バイトが最大であるかな、と言う訳です。