File
. 彼の作品についてはここで読むことができます。しかし、Java 7 では、この言語の作成者はファイルとディレクトリの操作方法を変更することにしました。File
これは、このクラスには多くの欠点があるという事実によるものでした。たとえば、copy()
ある場所から別の場所にファイルをコピーできるメソッド (明らかに必要と思われる機能) がありませんでした。さらに、このクラスには、値File
を返すメソッドが多数ありましたboolean
。エラーが発生した場合、このようなメソッドは例外をスローするのではなくfalseを返すため、エラーの診断と原因の特定が非常に困難になります。単一のクラスではなく、 、、のFile
3 つのクラスが出現しました。正確に言えば、これはクラスではなくインターフェイスです。それぞれがどのように異なるのか、そしてそれぞれがなぜ必要なのかを見てみましょう。最も簡単なことから始めましょう - 。 Paths
Path
Files
Path
Paths
パス
Paths
は、単一の静的メソッドを備えた非常に単純なクラスですget()
。これは、渡された string または URI から type のオブジェクトを取得するためだけに作成されましたPath
。他の機能はありません。彼の作品の一例を次に示します。
import java.nio.file.Path;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) {
Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
}
}
一番難しいクラスではないですよね?:) さて、タイプのオブジェクトを取得したのでPath
、それが何であるか、そしてなぜそれが必要であるかを理解しましょうPath
:)
パス
Path
は概して、 の再設計された類似物ですFile
。を使用するよりもはるかに簡単に作業できますFile
。 まず、多くのユーティリティ (静的) メソッドがそこから削除され、クラスに移動されましたFiles
。 次に、Path
メソッドの戻り値が順序付けされました。クラスでは、File
メソッドは this String
、 that boolean
、 thatを返しましたがFile
、それを理解するのは簡単ではありませんでした。たとえば、getParent()
現在のファイルの親パスを文字列として返すメソッドがありました。しかし同時に、getParentFile()
同じものをオブジェクトの形式で返すメソッドもありましたFile
。これは明らかに冗長です。したがって、インターフェイスでは、ファイルを操作するためのPath
メソッドgetParent()
やその他のメソッドは単にオブジェクトを返しますPath
。たくさんのオプションはありません - すべてが簡単でシンプルです。 どのような便利なメソッドがあるのでしょうかPath
? 以下にその一部とその仕事の例を示します。
-
getFileName()
— パスからファイル名を返します。 -
getParent()
- 現在のパスに関連する「親」ディレクトリ (つまり、ディレクトリ ツリーの上位のディレクトリ) を返します。 -
getRoot()
— 「ルート」ディレクトリを返します。つまり、ディレクトリツリーの最上位にあるものです。 -
startsWith()
,endsWith()
— パスが渡されたパスで始まる/終わるかどうかを確認します。import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); Path fileName = testFilePath.getFileName(); System.out.println(fileName); Path parent = testFilePath.getParent(); System.out.println(parent); Path root = testFilePath.getRoot(); System.out.println(root); boolean endWithTxt = testFilePath.endsWith("Desktop\\testFile.txt"); System.out.println(endWithTxt); boolean startsWithLalala = testFilePath.startsWith("lalalala"); System.out.println(startsWithLalala); } }
コンソール出力:
testFile.txt
C:\Users\ユーザー名\Desktop
C:\
true
falseこのメソッドがどのように機能するかに注目してください
endsWith()
。現在のパスが渡されたパスで終わるかどうかを確認します。これはパス上にあり、文字セット上にはありません。これら 2 つの呼び出しの結果を比較してください。
import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath.endsWith("estFile.txt")); System.out.println(testFilePath.endsWith("Desktop\\testFile.txt")); } }
コンソール出力:
真偽
_単なる文字のセットではなく、メソッドへの完全なパスを渡す必要があります。 そうしないと、現在のパスが実際にはそのような文字のシーケンスで終わっている場合でも (「estFile.txt」の場合のように)、結果は常にfalse
endsWith()
になります。」(上の例では)。さらに、絶対 (完全) パスと相対パスの操作を簡素化する一連のメソッドがあります
Path
。
-
boolean isAbsolute()
—現在のパスが絶対パスの場合はtrueを返します。import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath.isAbsolute()); } }
コンソール出力:
真実
-
Path normalize()
— 現在のパスを「正規化」し、不必要な要素を削除します。一般的なオペレーティング システムでは、パスを示すときに「.」文字がよく使用されることをご存知かもしれません。(「現在のディレクトリ」) および「..」(親ディレクトリ)。例: 「./Pictures/dog.jpg」は、現在いるディレクトリに Pictures フォルダーがあり、その中にファイル「dog.jpg」があることを意味します。それで、ここにあります。プログラムに「.」を使用したパスがある場合。または「..」の場合、メソッドは
normalize()
それらを削除し、それらを含まないパスを取得します。import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path path5 = Paths.get("C:\\Users\\Java\\.\\examples"); System.out.println(path5.normalize()); Path path6 = Paths.get("C:\\Users\\Java\\..\\examples"); System.out.println(path6.normalize()); } }
コンソール出力:
C:\Users\Java\examples
C:\Users\examples -
Path relativize()
— 現在のパスと渡されたパスの間の相対パスを計算します。例えば:
import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path testFilePath1 = Paths.get("C:\\Users\\Users\\Users\\Users"); Path testFilePath2 = Paths.get("C:\\Users\\Users\\Users\\Users\\Username\\Desktop\\testFile.txt"); System.out.println(testFilePath1.relativize(testFilePath2)); } }
コンソール出力:
ユーザー名\デスクトップ\testFile.txt
Path
非常に膨大です。これらはすべてOracle のドキュメントに記載されています。レビューに進みますFiles
。
ファイル
Files
- これは、クラスの静的メソッドが移動されたユーティリティ クラスですFile
。- これはまたは とFiles
ほぼ同じですが、ファイルのみで動作し、配列やコレクションでは動作しません:) ファイルとディレクトリの管理に重点を置いています。静的メソッドを使用すると、ファイルやディレクトリを作成、削除、移動できます。これらの操作には、メソッド(ディレクトリの場合 - )およびが使用されます。使用方法は次のとおりです。 Arrays
Collections
Files
createFile()
createDirectory()
move()
delete()
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class Main {
public static void main(String[] args) throws IOException {
//file creation
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println("Was the file created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// create directory
Path testDirectory = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory"));
System.out.println("Was the directory successfully created?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory")));
//move file from desktop to testDirectory. You need to move with the name of the file in the folder!
testFile1 = Files.move(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Is our file left on the desktop?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println("Has our file been moved to testDirectory?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
//remove file
Files.delete(testFile1);
System.out.println("Does the file still exist?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory\\testFile111.txt")));
}
}
Files.createFile()
ここでは、まずデスクトップに ファイルを作成し (メソッド)、次にそこにフォルダーを作成します (メソッドFiles.createDirectory()
)。その後、ファイル (メソッドFiles.move()
) をデスクトップからこの新しいフォルダーに移動し、最後にファイルを削除します (メソッドFiles.delete()
)。 コンソール出力: ファイルは正常に作成されましたか? true ディレクトリは正常に作成されましたか? true ファイルはまだデスクトップ上にありますか? false ファイルは testDirectory に移動されましたか? true ファイルはまだ存在しますか? 間違い 注意してください:インターフェイス メソッドと同様にPath
、多くのメソッドはFiles
オブジェクトを返しますPath
。ほとんどのクラス メソッドはFiles
も受け入れますPath
。ここではメソッドがあなたの忠実なアシスタントになりますPaths.get()
- 積極的に使用してください。他に何が面白いですかFiles
?古いクラスに実際に欠けていたのは、!File
メソッドでした。copy()
講義の冒頭で彼のことについて話しましたが、今度は彼にお会いするときです!
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class Main {
public static void main(String[] args) throws IOException {
//file creation
Path testFile1 = Files.createFile(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt"));
System.out.println("Was the file created successfully?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
// create directory
Path testDirectory2 = Files.createDirectory(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2"));
System.out.println("Was the directory successfully created?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2")));
//copy the file from the desktop to the directory testDirectory2.
testFile1 = Files.copy(testFile1, Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt"), REPLACE_EXISTING);
System.out.println("Is our file left on the desktop?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testFile111.txt")));
System.out.println("Has our file been copied to testDirectory?");
System.out.println(Files.exists(Paths.get("C:\\Users\\Username\\Desktop\\testDirectory2\\testFile111.txt")));
}
}
コンソール出力: ファイルは正常に作成されましたか? true ディレクトリは正常に作成されましたか? true ファイルはまだデスクトップ上にありますか? true ファイルは testDirectory にコピーされましたか? true プログラムでファイルをコピーできるようになりました。:) しかし、このクラスを使用すると、Files
ファイル自体を管理するだけでなく、その内容を操作することもできます。データをファイルに書き込むには 、write()
読み取りには 3 つのメソッドがありますread()
。 後者については詳しく説明しますreadAllBytes()
。readAllLines()
なぜその上にあるのでしょうか?それは非常に興味深い戻り値の型を持っているからです - List<String>
! つまり、ファイル内の行のリストが返されます。もちろん、ファイル全体を 1 行ずつ通常のループでコンソールに出力できるため、コンテンツの操作が非常に便利になりますfor
。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main {
public static void main(String[] args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);
for (String s: lines) {
System.out.println(s);
}
}
}
コンソール出力: 素晴らしい瞬間を覚えています: あなたは私の前に現れました、つかの間のビジョンのように、純粋な美しさの天才のように。 とっても快適!:) この機能は Java 7 で登場しました。Java 8 では、関数型プログラミングのいくつかの要素を Java に追加したStream APIが登場しました。ファイルを操作するためのより豊富な機能が含まれています。ファイル内の「How」という単語で始まるすべての行を検索し、それらを大文字に変換してコンソールに出力するというタスクがあると想像してください。Java 7 のクラスを使用したソリューションはどのFiles
ようなものになるでしょうか? このようなもの:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main {
public static void main(String[] args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"), UTF_8);
List<String> result = new ArrayList<>();
for (String s: lines) {
if (s.startsWith("How")) {
String upper = s.toUpperCase();
result.add(upper);
}
}
for (String s: result) {
System.out.println(s);
}
}
}
コンソール出力: 断食のビジョンのように、純粋な美しさの天才のように。 それはできたようですが、このような単純なタスクの割に、コードが少し...冗長になってしまったとは思いませんか? Java 8 Stream API を使用すると、ソリューションはより洗練されたものになります。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
Stream<String> stream = Files.lines(Paths.get("C:\\Users\\Username\\Desktop\\pushkin.txt"));
List<String> result = stream
.filter(line -> line.startsWith("How"))
.map(String::toUpperCase)
.collect(Collectors.toList());
result.forEach(System.out::println);
}
}
同じ結果が得られましたが、コードは大幅に減りました。また、「読みやすさ」においても負けているとは言えません。Stream API に詳しくなくても、このコードの動作については簡単にコメントできると思います。しかし、要するに、ストリームはさまざまな機能を実行できる一連の要素です。メソッドから Stream オブジェクトを取得しFiles.lines()
、それに 3 つの関数を適用します。
-
このメソッドを使用して、
filter()
ファイルから「How」で始まる行のみを選択します。 -
このメソッドを使用して選択されたすべての行を調べ
map()
、それぞれを大文字に変換します。 -
結果の行をすべて結合して、
List
を使用しますcollect()
。
Files.walkFileTree()
。やるべきことは次のとおりです。まず、 が必要ですFileVisitor
。FileVisitor
は、ファイル ツリーを移動するためのすべてのメソッドを説明する特別なインターフェイスです。具体的には、ファイルの内容を読み取り、必要なテキストが含まれているかどうかを確認するロジックをそこに配置します。これは私たちのものは次のようになりますFileVisitor
:
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
public class MyFileVisitor extends SimpleFileVisitor<Path> {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
List<String> lines = Files.readAllLines(file);
for (String s: lines) {
if (s.contains("This is the file we need")) {
System.out.println("Required file found!");
System.out.println(file.toAbsolutePath());
break;
}
}
return FileVisitResult.CONTINUE;
}
}
この場合、クラスは から継承しますSimpleFileVisitor
。これは を実装するクラスでありFileVisitor
、オーバーライドする必要があるメソッドは 1 つだけですvisitFile()
。ここでは、各ディレクトリ内の各ファイルに対して何を行う必要があるかを説明します。より複雑なトラバーサル ロジックが必要な場合は、独自の実装を作成する必要がありますFileVisitor
。そこでさらに 3 つのメソッドを実装する必要があります。
-
preVisitDirectory()
— フォルダーに入る前に実行する必要があるロジック。 -
visitFileFailed()
— ファイルの入力が不可能な場合(アクセスできない、またはその他の理由)、どうすればよいですか。 -
postVisitDirectory()
— フォルダーに入った後に実行する必要があるロジック。
SimpleFileVisitor
。メソッド内のロジックはvisitFile()
非常に単純です。ファイルからすべての行を読み取り、必要なコンテンツが含まれているかどうかを確認し、含まれている場合はコンソールへの絶対パスを出力します。問題を引き起こす可能性がある唯一の行は次の行です。
return FileVisitResult.CONTINUE;
実際、すべてがシンプルです。ここでは、ファイルが入力され、必要な操作がすべて完了した後にプログラムが何をすべきかを簡単に説明します。この場合、ツリーのトラバースを続ける必要があるため、オプションを選択しますCONTINUE
。しかし、たとえば、「これは必要なファイルです」を含むすべてのファイルを見つけるのではなく、そのようなファイルを 1 つだけ見つけるという別のタスクを行うこともできます。この後、プログラムを終了する必要があります。この場合、コードはまったく同じに見えますが、break ではありません。こうなるでしょう:
return FileVisitResult.TERMINATE;
それでは、コードを実行して、機能するかどうかを確認してみましょう。
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Files.walkFileTree(Paths.get("C:\\Users\\Username\\Desktop\\testFolder"), new MyFileVisitor());
}
}
コンソール出力: 必要なファイルが見つかりました。C:\Users\ユーザー名\Desktop\testFolder\FileWeNeed1.txt 必要なファイルが見つかりました。C:\Users\ユーザー名\Desktop\testFolder\level1-a\level2-aa\FileWeNeed2.txt 必要なファイルが見つかりました。C:\Users\Username\Desktop\testFolder\level1-b\level2-bb\FileWeNeed3.txt 見事、できました。:) について詳しく知りたい場合は、この記事walkFileTree()
をお勧めします。また、小さなタスクを完了することもできます。それを通常のタスクに置き換え、4 つのメソッドをすべて実装し、このプログラムの目的を考え出します。たとえば、すべてのアクションを記録するプログラムを作成できます。ファイルまたはフォルダーの名前を入力する前/後にコンソールに表示されます。以上です - それではまた! :) SimpleFileVisitor
FileVisitor
GO TO FULL VERSION