• ベストアンサー

java.io.Fileクラスは絶対パス長をチェックしないのですか?

windows XP+Eclipse3.3+JDK1.5.0_15上でjava.io.Fileクラスを使ってテキストファイルの入出力を行うJavaプログラムを作成しました。 しかし、これによって、パス長が長すぎて(フルパスで300文字)アクセスできないファイルが作成されてしまいました。 (正確には、Windowsのファイルエクスプローラーに存在は表示されているけど、開けないし、削除も、ドラッグアンドドロップもできないという状態。このファイルの右クリックメニューの項目は「開く」と「送る」の2つしかありませんでした。) StreamReader・WriterもIOExceptionを返していませんでした。 Fileクラスは読み書きするにあたってパス長のチェックをしていないのでしょうか? ちなみに、フルパス長259文字のテキストファイル(数行の文字列を記入してある)を入力に与えたとき、空ファイルのように扱われていました。 このファイルをメモ帳で開こうとすると「パス長が長すぎる」というエラーが出て中身が読み取れませんでした。 以下にソース(例外処理を省略)を抜粋します。 ---------------- File inputFile = new File(args[i]); if (!inputFile.isFile() || !inputFile.canRead()) { // ファイルを読む inputStream = new FileInputStream(inputFile); InputStreamReader inputStreamReader = new InputStreamReader( inputStream, "UTF-8"); bufferReader = new BufferedReader(inputStreamReader);   (以下、読み出し処理) // 入力ファイルと同じ階層に「Result」ディレクトリを作る File resultDir = new File(resultDirPath); resultDir.mkdir(); // 読み取った1行の末尾に"a"を付加したものをファイルに書き込み、 // 「Result」ディレクトリに出力。 // ファイル名は「output_(入力テキストファイル名)」とする File outputFile = new File(resultDir.getOutputDirPath(), outputFileName); outputFile.createNewFile(); outputStream = new FileOutputStream(outputFile); outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); bufferedWriter = new BufferedWriter(outputStreamWriter);   (以下、書き込み処理) } ---------------- 以上、よろしくお願いいたします。

  • SSMSE
  • お礼率25% (17/67)
  • Java
  • 回答数5
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
noname#94983
noname#94983
回答No.5

プログラムを実行し、最大パス長を超えてファイルが作れない!となれば、ネイティブ環境側(OS側)で問題が発生するわけで、それを受けて(Javaのプログラム内では)例外が発生する。例外が起こらずファイル保存できたということは、OS側で問題なくファイルが作成できた、すなわち最大パス長以内でファイルができている、ということ。したがって、Java側のクラスに、現在動いているネイティブ環境に合わせたファイルの最大パス長をチェックする仕組みが必要とは思われない。 XPで採用されているNTFSというファイルシステムでは、最大パス長は255でも259でも260でもなく、32768になる。したがって、ファイルのパス長が300文字なら全く問題は起こらない。300文字のパスのファイルが作成できるのは当然だし、できないほうがおかしい。 ただし、現実問題として、エクスプローラを始めとする大半のWindows用プログラムが、それ以前のWindowsで採用されていたFAT32ファイルシステムとの下位互換性を保つために、すべて「最大32768文字」に対応しておらず、わざと(XPのファイルシステムであるNTFSではなく、それよりも古い)FAT32に準拠した最大パス長の制約内でしか動かないように作られているため、それらのプログラムでファイルが利用できないに過ぎない。 だから、これはきわめてWindows的な問題であると思う。Windowsの下位互換にあわせて最大パス長を調整する、というのであれば、自分で実装するしかないと思う。

SSMSE
質問者

お礼

お礼が遅くなりました。 最終的に、受理する最大パス長を255文字までにする、という制約を設けるという方法をとりました。 結局 > フルパス長259文字のテキストファイル(数行の文字列を記入してある)を入力に与えたとき、空ファイルのように扱われていました。 の原因はわからずじまいでしたが・・・上記の制約によってこの現象が起きることを防げるので、とりあえずはよいことにしようと思います。

SSMSE
質問者

補足

> XPで採用されているNTFSというファイルシステムでは、最大パス長は255でも259でも260でもなく、32768になる。 (中略) > FAT32に準拠した最大パス長の制約内でしか動かないように作られているため、それらのプログラムでファイルが利用できないに過ぎない。 なるほど、そういうことだったのですね! エクスプローラーでは存在を確認できる→OS的には問題なくファイルとして取り扱われている メモ帳で開けない→メモ帳自体に課せられた制約のせい というように、それぞれの事象の原因はちがっていたのですね。 上記を踏まえて、パス長をどう扱うか、再考してみたいと思います。 丁寧な説明をいただき、有難うございました。

その他の回答 (4)

  • HarukaV49
  • ベストアンサー率53% (48/89)
回答No.4

>> ファイル名の文字数制限は、OSまたはそのファイルシステムによって異なります。 >これは理解しています。 これを理解しておられながら、ご自身でフィルタを設計しようとされないのはなぜですか? >C言語ではよくパス長をチェックするロジックにお目にかかった(多数の検索結果を得た)のですが、 >Javaではそういうのはないのでしょうか? C言語のものを移植するのでは、問題があるのですか? 第三者には、MacOS7でもFAT32でもアクセスできる必要があるのか等、使用環境を想定できないので、 フィルタを設計する方法はないと思うのですが、何をお望みなのでしょう。 >そもそも、なぜ、普通にはアクセスできないようなファイルを読み出したり、 >新規作成したりできるのでしょうか? javaで書き込んだファイルがjavaで読み出せないというような事象が起こっていますか? 最小限のサンプルコードをお示しください。

SSMSE
質問者

補足

> javaで書き込んだファイルがjavaで読み出せないというような事象が起こっていますか? 上記に関しては未検証です。 ただ、質問の中でも述べていますが、 > フルパス長259文字のテキストファイル(数行の文字列を記入してある)を入力に与えたとき、空ファイルのように扱われていました。 という事象が起こっているため、これはファイルオープンなどの例外がスローされてしかるべきではないのか?と疑問に思ったのです。

  • hrm_mmm
  • ベストアンサー率63% (292/459)
回答No.3

windowsでは、短いファイル名という別名(というかMSDOS時代の古い記述法)でアクセスすることが出来ます ファイル名だけでなくディレクトリー名も8文字+.+3文字拡張子に削ってアクセスします。 短いファイル名で、255バイト以内に収まれば、メモ帳でも短いファイル名でアクセス可能なはずです。これがwindowsのファイルパスの限界だったと記憶してますが。 例 D:\web\web_page\HTML4Transitional\長ーーーーーーーい.html ↓短いファイル名モード 8文字+.+3文字拡張子 D:\web\web_page\HTML4T~1\長ーー~1.HTM java.io.Fileクラスが直接この変換をやってるのか、JVMで変換してるのかOS側で変換しているのかまでは、やってみたことはないので解りませんが。

SSMSE
質問者

補足

こんな方法があったとは・・・ インターネット一時ファイルや%temp%フォルダに格納されているファイルで、提示いただいたような名前のものを見かけたことがありますが、あれはきっとこういうことだったのですね。 ひとつ勉強になりました。

  • HarukaV49
  • ベストアンサー率53% (48/89)
回答No.2

ファイル名の文字数制限は、OSまたはそのファイルシステムによって異なります。 ですから、java.io.Fileクラスは絶対パス長をチェックすることはできません。

SSMSE
質問者

補足

> ファイル名の文字数制限は、OSまたはそのファイルシステムによって異なります。 これは理解しています。 C言語ではよくパス長をチェックするロジックにお目にかかった(多数の検索結果を得た)のですが、Javaではそういうのはないのでしょうか? そもそも、なぜ、普通にはアクセスできないようなファイルを読み出したり、新規作成したりできるのでしょうか?

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

java.io.File インタフェイスみたいですけど。 javadocに、ファイルのパス長をチェックしてくれるような記述はないので、 java.io.File によるチェックは行われないみたいですね。

SSMSE
質問者

補足

javadocには、確かにパス長については何一つ言及していませんね・・・ java.io.Fileも、FileInputStreamも、InputStreamReaderも、 BufferedReaderも・・・標準アプリケーション(メモ帳)でさえ読み出せないようなデータをなぜ例外を吐かずに読んでいるのか、非常に不思議です。 Javaでファイルパス長をチェックするようなサンプルソースなどがないか検索してみたのですが、見つけることができませんでした。 誰もそんなチェックを実装していない、ということなんでしょうかね・・・??

関連するQ&A

  • プログラミングを始めたばかりの初心者です

    プログラミングを始めたばかりの初心者で、行き詰っていることがあります。 Windows環境でjavaのプログラミングをしています。(JDK1.7.0_03) InputFileというファイルを、指定したバイト単位で文字を切り出し、新たなOutputFileという ファイルに書き出したいのですが、以下の例のように、全角マイナスだけが?と表示されて しまい、うまくいきません。 InputFile 田中太郎 tanaka tarou  タナカタロウ 田中町1-1-1 06011112222・・・ 吉田花子 yoshida hanako ヨシダハナコ 吉田町2-2-2 01011113333・・・ 山田良子 yamada yoshiko ヤマダヨシコ 山田町3-3-3 02011115555・・・ OutputFile 田中太郎 tanaka tarou  タナカタロウ 田中町1?1?1 06011112222・・・ 吉田花子 yoshida hanako ヨシダハナコ 吉田町2?2?2 01011113333・・・ 山田良子 yamada yoshiko ヤマダヨシコ 山田町3?3?3 02011115555・・・ お見せするのも恥ずかしい滅茶苦茶なソースかもしれませんが現状は以下の通りです。 どなたか教えていただけないでしょうか。よろしくお願い致します。 (読み込むInputFileというファイルの文字コードはEUCです。) ソース import java.io.*; class ReadTest{ static LineNumberReader inr; static InputStreamReader isr; static String FN = "InputFile"; static OutputStreamWriter osw; public static void main(String[] args) { String line; try { FileInputStream fis = new FileInputStream(FN); isr = new InputStreamReader(fis,"EUC_JP"); inr = new LineNumberReader(new BufferedReader(isr)); FileOutputStream fos = new FileOutputStream("OutputFile"); osw = new OutputStreamWriter(fos,"EUC_JP"); BufferedWriter bw = new BufferedWriter(osw); while ((line = inr.readLine()) != null) { bw.write(new String(line.getBytes(),0,120)); bw.newLine(); } System.out.println(inr.getLineNumber() + "件読み込み完了"); fis.close(); isr.close(); bw.close(); fos.close(); } catch (IOException e) { System.out.println(e); } } }

  • Javaを使ったチャットシステムについて

    はじめまして。 チャットシステムを作ろうと思い他の方が制作されたソースコードを拝見させて頂いたのですがよくわかりませんでした。 よろしければ教えて頂けないでしょうか? よくわからなかったのは読込・書込処理の部分です。 どういう流れで会話のやり取りが行われているのかよくわかりません。 例えば、Aさんが書き込んでBさんがその書き込みを見るまで、のような一連の流れです。 ・読込処理 URL wi_url = new URL(p_url+"chat1.cgi"); URLConnection wi_connect = wi_url.openConnection(); wi_connect.setDoInput(true); wi_connect.setDoOutput(true); wi_connect.setUseCaches(false); OutputStream wo_stream = wi_connect.getOutputStream(); BufferedWriter wo_buffer = new BufferedWriter(new OutputStreamWriter(wo_stream)); wo_buffer.write("read", 0, 4); wo_buffer.flush(); wo_buffer.close(); InputStream wi_stream = wi_connect.getInputStream(); BufferedReader wi_buffer= new BufferedReader(new InputStreamReader(wi_stream)); ・書込処理 URL wo_url = new URL(p_url+"chat2.cgi"); URLConnection wo_connect = wo_url.openConnection(); wo_connect.setDoOutput(true); wo_connect.setDoInput(true); wo_connect.setUseCaches(false); OutputStream wo_stream = wo_connect.getOutputStream(); BufferedWriter wo_buffer = new BufferedWriter(new OutputStreamWriter(wo_stream)); wo_buffer.write(w_data, 0, w_data.length()); wo_buffer.flush(); wo_buffer.close(); InputStream wi_stream = wo_connect.getInputStream(); BufferedReader wi_buffer = new BufferedReader(new InputStreamReader(wi_stream));

  • BufferedWriterのcloseメソッド

    ファイル出力に関して、次のようなコードをよく目にします。 例外処理省略 FileOutputStream fos = new FileOutputStream("hoge.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos); BufferedWriter bw = new BufferedWriter(osw); //ファイルに出力 bw.close(); osw.close(); fos.close(); 同様の処理で、次のようなコードも目にします。 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("hoge.txt"))); //ファイルに出力 bw.close(); 下のコードで、関連するソースを見てみると、BufferedWriterオブジェクトをcloseする際に、そのオブジェクトが参照を持っているOutputStreamWriterオブジェクトはcloseされているように見えるのですが、FileOutputStreamオブジェクトがcloseされているようには見えませんでした。 下のようなコードは安全といえるのでしょうか?BufferedWriterオブジェクトのcloseで引数として渡される各オブジェクトもcloseされるのでしょうか?

  • ファイルの書き出しについて、どちらのほうが良い方法でしょうか?

    下の2つのメソッドでどちらのほうがよいでしょうか? 実行時間的にはuseStringのほうが若干速いのですが... メモリ消費とかセオリーとか常識とかそういうのを含めて解説を頂きたいです。 今のところ結果は同じものが出力されています。 public static void useString() { try { System.out.println("start useString"); URL url = new URL("どこかのページ"); File outputFile = new File("test1.html"); InputStream input = url.openStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile.toString(), true)); String tmp = ""; String str; while ((str = reader.readLine()) != null) { writer.write(tmp); } reader.close(); input.close(); writer.write(tmp); writer.close(); } catch (IOException e) { e.printStackTrace(System.out); } } public static void useStream() { try { URL url = new URL("どこかのページ"); File outputFile = new File("test.html"); InputStream input = url.openStream(); FileOutputStream output = new FileOutputStream(outputFile); byte[] bytes = new byte[2048]; int n; while ((n = input.read(bytes)) >= 0) { output.write(bytes, 0, n); } input.close(); output.close(); } catch (IOException e) { e.printStackTrace(System.out); } }

    • ベストアンサー
    • Java
  • あるファイルを選択するには

    下のプログラムで形態素解析ツールの茶筌を呼び出しています。 任意のファイルを選びそこに書かれているテキストを茶筌にかけたいと思っています。任意のファイルを選ぶためにはどのようにすればよいのか困っています。 是非お願いします。 import java.*; import java.io.*; import java.util.*; class test1 { public static void main(String[] arg) { String result; System.out.println(arg[0]); ChasenHandler ch = new ChasenHandler(); result = ch.doChasen(arg[0]); System.out.println(result); } } class ChasenHandler { StringTokenizer stn; String CHASEN_COMMAND[] = {"chasen"}; String CHASEN_END = "EOS"; Process process; BufferedWriter chasen_writer; BufferedReader chasen_reader; public ChasenHandler () { try { process = Runtime.getRuntime ().exec (CHASEN_COMMAND); } catch (IOException e) { System.out.println ("Error in ChasenHandler"); return; } InputStream is = process.getInputStream (); chasen_reader = new BufferedReader (new InputStreamReader (is)); OutputStream os = process.getOutputStream (); chasen_writer = new BufferedWriter (new OutputStreamWriter (os)); } String doChasen (String input) { String result = ""; try { chasen_writer.write (input , 0 , input.length()); chasen_writer.newLine (); chasen_writer.flush (); String line = ""; while (true) { if ((line = chasen_reader.readLine ()).equals (CHASEN_END)) { result = result + "EOS"; break; } result = result + line + ""; } } catch (Exception ie) { result = "\n"; ie.printStackTrace (); System.exit (0); } input = ""; return result; } }

    • ベストアンサー
    • Java
  • Javaで名前付きパイプ

    Windows上でJavaとFortranを使用し、プロセス間通信を行いと考えています。単純に思いついたのが名前付きパイプなのですが、Javaで名前付きパイプを生成する方法が解りません。 どなたかご存じないでしょうか? ちなみに、 try { // ファイルオブジェクトを生成する file.createNewFile(); FileOutputStream fileOutputStream = new FileOutputStream("\\\\.\\PIPE\\mypipe");<<ここでエラーになる。 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream); BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); // ファイルに書き込む内容をセットする String outputdata = "TESTDATA";   <<< 以下省略 >>>> こんな感じで、試してみたのですが、ファイルの生成ができませんでした。 色々と調べてはいるのですが、どなたか成功した方いらっしゃいませんか?最悪はJNIを利用するしかないのかなぁ?

  • javaについて>IEのクッキーを使いたい

    IEでログインした状態であれば、ヤフーメールなどクッキーを使うHPにアクセスできるかと思ったのですがアクセスできません。どうすればよいでしょうか? 多分、javaはIEのクッキーを利用していないのですよね・・・ 何とか、IEのクッキーを利用できれば良いのですが。何か、良いお知恵はありませんでしょうか? 宜しくお願い致します。 以下、コードです。 ーーーーーーーーーーーーーーーーーーーーーーー import java.io.*; import java.net.*; class Test { static String input() throws IOException { InputStream is = new FileInputStream("url.txt");//urlを入力 BufferedReader br = new BufferedReader(new InputStreamReader(is)); String str = br.readLine(); return(str); } static void read(String str) throws IOException { OutputStream os = new FileOutputStream("log.txt",true); BufferedWriter fr = new BufferedWriter(new OutputStreamWriter(os)); URL url = new URL(str); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(),"JISAutoDetect")); for (;;) { String i = in.readLine(); if(i == null) { break; } System.out.println(i + "\n"); fr.write(i + "\n"); } in.close(); fr.close(); } public static void main(String[] args) throws IOException { Test brow = new Test(); brow.read(brow.input()); } }

    • ベストアンサー
    • Java
  • ログファイルの文字化け

    以前、ここでログ部品の作り方を教えていただきました。 ありがとうございます。 サーバーはUNIXでTOMCATを使っています。 ログインしてからTOMCATを起動するとログは正常に出るのですが、ログインせずにAUTOでTOMCATを起動するとログが文字化けしてしまいます。 File file = new File("log.log"); FileOutputStream OpS = new FileOutputStream(file.getPath(), true); BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(OpS)); BW.write(value); BW.newLine(); BW.close(); といった形で作っているのですが、何かよい方法はないでしょうか?

    • ベストアンサー
    • Java
  • 半角カナが含まれる文字列をファイル出力

    いつもお世話になっております。 以下のようにしてテキストファイルを出力 していますが、半角カナの出力時に文字化けして しまいます。 ------------------------------------------ FileOutputStream os = new FileOutputStream("D:\\java_src\\test1.txt"); OutputStreamWriter osw = new OutputStreamWriter(os,"Shift_JIS"); BufferedWriter writer = new BufferedWriter(osw); writer.write("テキヨウ"); writer.close(); osw.close(); os.close(); ------------------------------------------ 出力されるテキストファイルは 文字コード:Shift_JIS 改行コード:CRLF としたいのですが何かいい方法はありますでしょうか? 動作環境は WindowsXP + JDK5.0 です。 すいませんが、宜しくお願いします。

  • UNICODEへの文字コード変換

    以下のようにして、 日本語で書かれたファイルを読み込んで、 UNICODEに変換したいのですが、 できません。。。 どこが間違っているのでしょうか?(;;) 元の日本語ファイル「こんにちは」 >>できたファイル「\u3053\u3093\u306b\u3061\u306f」 という風にしたいのですが。。 //FileIOSteramの作成 FileInputStream fis = new FileInputStream(iFile); FileOutputStream fos = new FileOutputStream(oFile); //Stream ラップ InputStreamReader in = new InputStreamReader(fis, "EUC-JP-LINUX"); OutputStreamWriter out = new OutputStreamWriter(fos, "UTF16"); System.out.println(System.getProperty("file.encoding")); //読み込みと書き込み int c; InputStreamReader in = new InputStreamReader(fis, "Unicode"); Writer out = new Writer(fos); while((c = in.read()) != -1){ out.write(c); }

専門家に質問してみよう