次のコードを使用してファイルをコピーしようとしています。
File targetFile = new File(targetPath + File.separator + filename);
...
targetFile.createNewFile();
fileInputStream = new FileInputStream(fileToCopy);
fileOutputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[64*1024];
int i = 0;
while((i = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, i);
}
一部のユーザーはtargetFile.createNewFile
この例外が発生します:
Java.io.IOException: The filename, directory name, or volume label syntax is incorrect
at Java.io.WinNTFileSystem.createFileExclusively(Native Method)
at Java.io.File.createNewFile(File.Java:850)
ファイル名とディレクトリ名は正しいようです。コピーコードが実行される前に、ディレクトリtargetPath
の存在がチェックされ、ファイル名は次のようになります。AB_timestamp.xml
ユーザーにはtargetPath
への書き込み権限があり、OSを使用して問題なくファイルをコピーできます。
私はマシンにアクセスできないので、これはまだ起こっており、自分のマシンでは問題を再現できません。この例外の理由についてのヒントを求めます。
TargetPathとfilenameの間のパスにあるディレクトリ区切り文字の調整に注意するため、これを試してください。
File targetFile = new File(targetPath, filename);
これは、ファイル名にコロン付きのタイムスタンプがある場合に発生する可能性があります。 myfile_HH:mm:ss.csv
コロンを削除すると問題が修正されました。
同じ問題が発生しました。それは書き込みアクセス許可と関係があると思います。 c:\に書き込もうとしたときにエラーが発生しましたが、D:\に変更すると、すべて正常に動作しました。どうやらJavaには私のシステムドライブに書き込む権限がありませんでした(CにインストールされているWindows 7を実行している:)
ここに私が使用するテストプログラムがあります
import Java.io.File;
public class TestWrite {
public static void main(String[] args) {
if (args.length!=1) {
throw new IllegalArgumentException("Expected 1 argument: dir for tmp file");
}
try {
File.createTempFile("bla",".tmp",new File(args[0]));
} catch (Exception e) {
System.out.println("exception:"+e);
e.printStackTrace();
}
}
}
別のディレクトリにファイルを作成してみてください-例:そのディレクトリへの書き込みアクセス権があることを確認した後の「C:\」。それが機能する場合、ファイルのパス名が間違っています。
例外のコメントを見て、ファイルのパス名のすべての要素を変更してみてください。実験。結論を導き出す。
TargetPathがディレクトリであること、またはその名前の何かが存在することを確認しますか? (私はあなたがユーザーがそれをオペレーティングシステムからコピーできると言いますが、多分彼らは他のものをタイプしているでしょう)。
TargetPathはすでにFile.separatorで終わっていますか?
(失敗した場合のtargetPathとfilenameの値をログに記録して教えていただければ助かります)
たぶん問題は、ファイルをネットワーク経由で共有ドライブにコピーしていることですか? Javaパスが\ mypc\mysharedフォルダのようなパスである場合、NFSを使用してファイルを書き込むときに問題が発生する可能性があると思います。
この問題が発生する経路は何ですか?
自分のマシンでエラーを再現したり、コードが失敗したユーザーのマシンを手に入れたりすることができなかったので、私は今まで受け入れられた答えを宣言するのを待っていました。コードを次のように変更しました。
File parentFolder = new File(targetPath);
... do some checks on parentFolder here ...
File targetFile = new File(parentFolder, filename);
targetFile.createNewFile();
fileInputStream = new FileInputStream(fileToCopy);
fileOutputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[64*1024];
int i = 0;
while((i = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, i);
}
その後、それは問題を報告するユーザーのために働きました。
それで、アレクサンダーズの答えがトリックをしたようです-私は実際に彼が与えたものとは少し異なるコンストラクターを使用していますが、同じ線に沿っています。
私はまだそのユーザーと話し合って、古いバージョンをもう一度実行し、それでも失敗するかどうかを確認することによって、コードの変更がエラーを修正したことを確認するのを手伝わなければなりません。
ところで。ロギングは適切に行われ、ログに記録されたパスは問題ないように見えました。私はそれを当たり前のことと見なし、問題のコードが不必要に複雑になっていることに気付きました。
役立つ回答をありがとう。
ロギングを追加して、ファイルが作成しようとしている名前とパスを正確に確認し、親がディレクトリであることを確認します。
さらに、ループを使用する代わりに、チャネルを確認することもできます。 ;-)
完全パスのファイル/フォルダー名に含まれる特殊文字をすべて削除します。
あなたは「一部のユーザーのために」と言います-それで、それは他のために働きますか?ここでの違いは何ですか、ユーザーは異なるマシンで異なるインスタンスを実行していますか、それとも同時ユーザーにサービスを提供するサーバーですか?
後者の場合、それはどういうわけか同時性のバグだと思います-2つのスレッドのチェックは、WinNTFileSystem.createFileExclusively(Native Method)で同時にファイルを作成しようとします。
OpenJDKソースを見ると、createNewFileもcreateFileExclusivelyも同期されていないため、このブロックを自分で同期する必要がある場合があります。
非常によく似たエラー:-「... Java.io.IOException:ファイル名、ディレクトリ名、またはボリュームラベルの構文が正しくありません」が、Tomcatのホーム設定にトレーニングのバックスラッシュがあると、Eclipseで生成されました。
- http://www.coderanch.com/t/556633/Tomcat/Java-io-IOException-filename-directory 修正されました。
ファイルがすでに存在している可能性があります。タイムスタンプの解像度が十分でない場合は、これが原因である可能性があります。これは取得しているIOExceptionであるため、権限の問題ではない可能性があります(この場合、SecurityExceptionが発生します)。
ファイルを作成する前に、まずファイルの存在を確認し、何が起こっているかをログに記録します。
使用しているメソッドの詳細については、 public boolean createNewFile() を参照してください。