Java Language
Plik I / O
Szukaj…
Wprowadzenie
Java I / O (Input and Output) służy do przetwarzania danych wejściowych i generowania danych wyjściowych. Java wykorzystuje koncepcję strumienia, aby przyspieszyć działanie operacji we / wy. Pakiet java.io zawiera wszystkie klasy wymagane do operacji wejścia i wyjścia. Obsługa plików odbywa się również w Javie przez interfejs API Java I / O.
Odczytywanie wszystkich bajtów do bajtu []
Java 7 wprowadziła bardzo przydatną klasę Files
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
Path path = Paths.get("path/to/file");
try {
byte[] data = Files.readAllBytes(path);
} catch(IOException e) {
e.printStackTrace();
}
Odczytywanie obrazu z pliku
import java.awt.Image;
import javax.imageio.ImageIO;
...
try {
Image img = ImageIO.read(new File("~/Desktop/cat.png"));
} catch (IOException e) {
e.printStackTrace();
}
Zapis bajtu [] do pliku
byte[] bytes = { 0x48, 0x65, 0x6c, 0x6c, 0x6f };
try(FileOutputStream stream = new FileOutputStream("Hello world.txt")) {
stream.write(bytes);
} catch (IOException ioe) {
// Handle I/O Exception
ioe.printStackTrace();
}
byte[] bytes = { 0x48, 0x65, 0x6c, 0x6c, 0x6f };
FileOutputStream stream = null;
try {
stream = new FileOutputStream("Hello world.txt");
stream.write(bytes);
} catch (IOException ioe) {
// Handle I/O Exception
ioe.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ignored) {}
}
}
Większość API plików java.io akceptować zarówno String
s i File
s jako argumenty, więc może również wykorzystanie
File file = new File("Hello world.txt");
FileOutputStream stream = new FileOutputStream(file);
Stream vs Writer / Reader API
Strumienie dostarczania najbardziej bezpośredni dostęp do zawartości binarnej, więc wszelkie InputStream
/ OutputStream
implementacje zawsze działają na int
s, a byte
s.
// Read a single byte from the stream
int b = inputStream.read();
if (b >= 0) { // A negative value represents the end of the stream, normal values are in the range 0 - 255
// Write the byte to another stream
outputStream.write(b);
}
// Read a chunk
byte[] data = new byte[1024];
int nBytesRead = inputStream.read(data);
if (nBytesRead >= 0) { // A negative value represents end of stream
// Write the chunk to another stream
outputStream.write(data, 0, nBytesRead);
}
Istnieją pewne wyjątki, prawdopodobnie przede wszystkim PrintStream
który dodaje „możliwość wygodnego drukowania reprezentacji różnych wartości danych”. Pozwala to na użycie System.out
zarówno jako binarnego InputStream
jak i tekstu wyjściowego przy użyciu metod takich jak System.out.println()
.
Ponadto niektóre implementacje strumienia działają jako interfejs do treści wyższego poziomu, takich jak obiekty Java (patrz Serializacja) lub typy rodzime, np. DataOutputStream
/ DataInputStream
.
Dzięki klasom Writer
i Reader
Java zapewnia również interfejs API dla jawnych strumieni znaków. Chociaż większość aplikacji będzie opierać te implementacje na strumieniach, interfejs API strumienia znaków nie ujawnia żadnych metod dla zawartości binarnej.
// This example uses the platform's default charset, see below
// for a better implementation.
Writer writer = new OutputStreamWriter(System.out);
writer.write("Hello world!");
Reader reader = new InputStreamReader(System.in);
char singleCharacter = reader.read();
Ilekroć konieczne jest zakodowanie znaków w danych binarnych (np. Przy użyciu klas InputStreamWriter
/ OutputStreamWriter
), należy określić zestaw znaków, jeśli nie chcesz polegać na domyślnym zestawie znaków platformy. W razie wątpliwości użyj kodowania zgodnego z Unicode, np. UTF-8, który jest obsługiwany na wszystkich platformach Java. Dlatego powinieneś trzymać się z dala od zajęć takich jak FileWriter
i FileReader
jak te zawsze używać charset domyślne platformy. Lepszym sposobem dostępu do plików przy użyciu strumieni znaków jest:
Charset myCharset = StandardCharsets.UTF_8;
Writer writer = new OutputStreamWriter( new FileOutputStream("test.txt"), myCharset );
writer.write('Ä');
writer.flush();
writer.close();
Reader reader = new InputStreamReader( new FileInputStream("test.txt"), myCharset );
char someUnicodeCharacter = reader.read();
reader.close();
Jednym z najczęściej używanych Reader
jest BufferedReader
który zapewnia metodę odczytu całych linii tekstu z innego czytnika i jest prawdopodobnie najprostszym sposobem na odczytanie strumienia znaków linia po linii:
// Read from baseReader, one line at a time
BufferedReader reader = new BufferedReader( baseReader );
String line;
while((line = reader.readLine()) != null) {
// Remember: System.out is a stream, not a writer!
System.out.println(line);
}
Odczytywanie całego pliku na raz
File f = new File(path);
String content = new Scanner(f).useDelimiter("\\Z").next();
\ Z jest symbolem EOF (koniec pliku). Po ustawieniu jako ogranicznik skaner będzie odczytywał wypełnienie do momentu osiągnięcia flagi EOF.
Odczytywanie pliku za pomocą skanera
Czytanie pliku linia po linii
public class Main {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(new File("example.txt"));
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
//do stuff
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
słowo po słowie
public class Main {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(new File("example.txt"));
while(scanner.hasNext())
{
String line = scanner.next();
//do stuff
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
możesz także zmienić delimetr, używając metody scanner.useDelimeter ()
Iterowanie po katalogu i filtrowanie według rozszerzenia pliku
public void iterateAndFilter() throws IOException {
Path dir = Paths.get("C:/foo/bar");
PathMatcher imageFileMatcher =
FileSystems.getDefault().getPathMatcher(
"regex:.*(?i:jpg|jpeg|png|gif|bmp|jpe|jfif)");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir,
entry -> imageFileMatcher.matches(entry.getFileName()))) {
for (Path path : stream) {
System.out.println(path.getFileName());
}
}
}
Migracja z java.io.File do Java 7 NIO (java.nio.file.Path)
W tych przykładach założono, że już wiesz, czym jest ogólnie NIO Java 7 i że jesteś przyzwyczajony do pisania kodu przy użyciu java.io.File
. Skorzystaj z tych przykładów, aby szybko znaleźć więcej dokumentacji zorientowanej na NIO do migracji.
NIO Java 7 oferuje znacznie więcej, np. Pliki mapowane w pamięci lub otwieranie pliku ZIP lub JAR za pomocą FileSystem . Przykłady te będą obejmować tylko ograniczoną liczbę podstawowych przypadków użycia.
Zgodnie z podstawową regułą, jeśli jesteś przyzwyczajony do wykonywania operacji odczytu / zapisu systemu plików za pomocą metody instancji java.io.File
, znajdziesz ją jako metodę statyczną w java.nio.file.Files
.
Wskaż ścieżkę
// -> IO
File file = new File("io.txt");
// -> NIO
Path path = Paths.get("nio.txt");
Ścieżki względem innej ścieżki
// Forward slashes can be used in place of backslashes even on a Windows operating system
// -> IO
File folder = new File("C:/");
File fileInFolder = new File(folder, "io.txt");
// -> NIO
Path directory = Paths.get("C:/");
Path pathInDirectory = directory.resolve("nio.txt");
Konwertowanie pliku z / na ścieżkę do użytku z bibliotekami
// -> IO to NIO
Path pathFromFile = new File("io.txt").toPath();
// -> NIO to IO
File fileFromPath = Paths.get("nio.txt").toFile();
Sprawdź, czy plik istnieje i usuń go, jeśli tak jest
// -> IO
if (file.exists()) {
boolean deleted = file.delete();
if (!deleted) {
throw new IOException("Unable to delete file");
}
}
// -> NIO
Files.deleteIfExists(path);
Zapisz do pliku za pośrednictwem OutputStream
Istnieje kilka sposobów zapisu i odczytu z pliku przy użyciu NIO dla różnych wydajności i pamięci ograniczeń, czytelność i przypadków użycia, takie jak FileChannel
, Files.write(Path path, byte\[\] bytes, OpenOption... options)
. .. W tym przykładzie omówiono tylko OutputStream
, ale zachęcamy do zapoznania się z plikami mapowanymi w pamięci i różnymi metodami statycznymi dostępnymi w java.nio.file.Files
.
List<String> lines = Arrays.asList(
String.valueOf(Calendar.getInstance().getTimeInMillis()),
"line one",
"line two");
// -> IO
if (file.exists()) {
// Note: Not atomic
throw new IOException("File already exists");
}
try (FileOutputStream outputStream = new FileOutputStream(file)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
// -> NIO
try (OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE_NEW)) {
for (String line : lines) {
outputStream.write((line + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
}
}
Iteracja każdego pliku w folderze
// -> IO
for (File selectedFile : folder.listFiles()) {
// Note: Depending on the number of files in the directory folder.listFiles() may take a long time to return
System.out.println((selectedFile.isDirectory() ? "d" : "f") + " " + selectedFile.getAbsolutePath());
}
// -> NIO
Files.walkFileTree(directory, EnumSet.noneOf(FileVisitOption.class), 1, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("d " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
Iteracja folderu rekurencyjnego
// -> IO
recurseFolder(folder);
// -> NIO
// Note: Symbolic links are NOT followed unless explicitly passed as an argument to Files.walkFileTree
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("d " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws IOException {
System.out.println("f " + selectedPath.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
private static void recurseFolder(File folder) {
for (File selectedFile : folder.listFiles()) {
System.out.println((selectedFile.isDirectory() ? "d" : "f") + " " + selectedFile.getAbsolutePath());
if (selectedFile.isDirectory()) {
// Note: Symbolic links are followed
recurseFolder(selectedFile);
}
}
}
Odczyt / zapis pliku przy użyciu FileInputStream / FileOutputStream
Napisz do pliku test.txt:
String filepath ="C:\\test.txt";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filepath);
byte[] buffer = "This will be written in test.txt".getBytes();
fos.write(buffer, 0, buffer.length);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fos != null)
fos.close();
}
Odczyt z pliku test.txt:
String filepath ="C:\\test.txt";
FileInputStream fis = null;
try {
fis = new FileInputStream(filepath);
int length = (int) new File(filepath).length();
byte[] buffer = new byte[length];
fis.read(buffer, 0, length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fis != null)
fis.close();
}
Zauważ, że od wersji Java 1.7 wprowadzono instrukcję try-with-resources, co znacznie ułatwiło implementację operacji odczytu / zapisu:
Napisz do pliku test.txt:
String filepath ="C:\\test.txt";
try (FileOutputStream fos = new FileOutputStream(filepath)){
byte[] buffer = "This will be written in test.txt".getBytes();
fos.write(buffer, 0, buffer.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Odczyt z pliku test.txt:
String filepath ="C:\\test.txt";
try (FileInputStream fis = new FileInputStream(filepath)){
int length = (int) new File(filepath).length();
byte[] buffer = new byte[length];
fis.read(buffer, 0, length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Odczytywanie z pliku binarnego
Możesz odczytać plik binarny za pomocą tego fragmentu kodu we wszystkich najnowszych wersjach Java:
File file = new File("path_to_the_file");
byte[] data = new byte[(int) file.length()];
DataInputStream stream = new DataInputStream(new FileInputStream(file));
stream.readFully(data);
stream.close();
Jeśli używasz Java 7 lub nowszej, istnieje prostszy sposób korzystania z nio API
:
Path path = Paths.get("path_to_the_file");
byte [] data = Files.readAllBytes(path);
Zamykający
Plik można zablokować za pomocą interfejsu API FileChannel
który można uzyskać z wejściowych streams
wyjściowych i readers
Przykład ze streams
// Otwórz strumień pliku FileInputStream ios = nowy FileInputStream (nazwa pliku);
// get underlying channel
FileChannel channel = ios.getChannel();
/*
* try to lock the file. true means whether the lock is shared or not i.e. multiple processes can acquire a
* shared lock (for reading only) Using false with readable channel only will generate an exception. You should
* use a writable channel (taken from FileOutputStream) when using false. tryLock will always return immediately
*/
FileLock lock = channel.tryLock(0, Long.MAX_VALUE, true);
if (lock == null) {
System.out.println("Unable to acquire lock");
} else {
System.out.println("Lock acquired successfully");
}
// you can also use blocking call which will block until a lock is acquired.
channel.lock();
// Once you have completed desired operations of file. release the lock
if (lock != null) {
lock.release();
}
// close the file stream afterwards
// Example with reader
RandomAccessFile randomAccessFile = new RandomAccessFile(filename, "rw");
FileChannel channel = randomAccessFile.getChannel();
//repeat the same steps as above but now you can use shared as true or false as the channel is in read write mode
Kopiowanie pliku przy użyciu InputStream i OutputStream
Możemy bezpośrednio skopiować dane ze źródła do ujścia danych za pomocą pętli. W tym przykładzie odczytujemy dane z InputStream i jednocześnie piszemy do OutputStream. Kiedy skończymy czytać i pisać, musimy zamknąć zasób.
public void copy(InputStream source, OutputStream destination) throws IOException {
try {
int c;
while ((c = source.read()) != -1) {
destination.write(c);
}
} finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
}
Odczytywanie pliku przy użyciu kanału i bufora
Channel
używa Buffer
do odczytu / zapisu danych. Bufor jest pojemnikiem o stałym rozmiarze, w którym możemy jednocześnie zapisać blok danych. Channel
jest znacznie szybszy niż we / wy oparte na strumieniu.
Aby odczytać dane z pliku przy użyciu Channel
, musimy wykonać następujące kroki:
- Potrzebujemy wystąpienia
FileInputStream
.FileInputStream
ma metodę o nazwiegetChannel()
która zwraca kanał. - Wywołaj
getChannel()
FileInputStream igetChannel()
kanał. - Utwórz ByteBuffer. ByteBuffer jest pojemnikiem o stałej wielkości bajtów.
- Kanał ma metodę odczytu i jako argument tej metody odczytu musimy podać ByteBuffer. ByteBuffer ma dwa tryby - nastrój tylko do odczytu i nastrój tylko do zapisu. Możemy zmienić tryb za pomocą wywołania metody
flip()
. Bufor ma pozycję, limit i pojemność. Po utworzeniu bufora o stałym rozmiarze jego limit i pojemność są takie same jak rozmiar, a pozycja zaczyna się od zera. Podczas gdy bufor jest zapisywany z danymi, jego pozycja stopniowo rośnie. Zmiana trybu oznacza zmianę pozycji. Aby odczytać dane z początku bufora, musimy ustawić pozycję na zero. Metoda flip () zmienia pozycję - Kiedy wywołujemy metodę odczytu
Channel
, wypełnia on bufor przy użyciu danych. - Jeśli musimy odczytać dane z
ByteBuffer
, musimy odwrócić bufor, aby zmienić jego tryb na „tylko do zapisu” na tryb „tylko do odczytu”, a następnie nadal czytać dane z bufora. - Gdy nie ma już danych do odczytu, metoda
read()
kanału zwraca 0 lub -1.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class FileChannelRead {
public static void main(String[] args) {
File inputFile = new File("hello.txt");
if (!inputFile.exists()) {
System.out.println("The input file doesn't exit.");
return;
}
try {
FileInputStream fis = new FileInputStream(inputFile);
FileChannel fileChannel = fis.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (fileChannel.read(buffer) > 0) {
buffer.flip();
while (buffer.hasRemaining()) {
byte b = buffer.get();
System.out.print((char) b);
}
buffer.clear();
}
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Kopiowanie pliku przy użyciu kanału
Możemy użyć Channel
do szybszego kopiowania zawartości pliku. Aby to zrobić, możemy użyć metody transferTo()
FileChannel
.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class FileCopier {
public static void main(String[] args) {
File sourceFile = new File("hello.txt");
File sinkFile = new File("hello2.txt");
copy(sourceFile, sinkFile);
}
public static void copy(File sourceFile, File destFile) {
if (!sourceFile.exists() || !destFile.exists()) {
System.out.println("Source or destination file doesn't exist");
return;
}
try (FileChannel srcChannel = new FileInputStream(sourceFile).getChannel();
FileChannel sinkChanel = new FileOutputStream(destFile).getChannel()) {
srcChannel.transferTo(0, srcChannel.size(), sinkChanel);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Odczytywanie pliku za pomocą BufferedInputStream
Odczytywanie pliku przy użyciu BufferedInputStream
zasadniczo szybsze niż FileInputStream
ponieważ utrzymuje on wewnętrzny bufor do przechowywania bajtów odczytanych z podstawowego strumienia wejściowego.
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class FileReadingDemo {
public static void main(String[] args) {
String source = "hello.txt";
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source))) {
byte data;
while ((data = (byte) bis.read()) != -1) {
System.out.println((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Zapisywanie pliku za pomocą kanału i bufora
Aby zapisać dane do pliku za pomocą Channel
, musimy wykonać następujące kroki:
- Najpierw musimy uzyskać obiekt
FileOutputStream
- Nabywać
FileChannel
wywołaniegetChannel()
metodę zFileOutputStream
- Utwórz
ByteBuffer
a następnie wypełnij go danymi - Następnie musimy wywołać metodę
flip()
ByteBuffer
i przekazać ją jako argument metodywrite()
FileChannel
- Kiedy skończymy pisać, musimy zamknąć zasób
import java.io.*;
import java.nio.*;
public class FileChannelWrite {
public static void main(String[] args) {
File outputFile = new File("hello.txt");
String text = "I love Bangladesh.";
try {
FileOutputStream fos = new FileOutputStream(outputFile);
FileChannel fileChannel = fos.getChannel();
byte[] bytes = text.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
fileChannel.write(buffer);
fileChannel.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}
Zapisywanie pliku za pomocą PrintStream
Możemy użyć klasy PrintStream
do napisania pliku. Ma kilka metod, które pozwalają wydrukować dowolne wartości typu danych. Metoda println()
dodaje nowy wiersz. Po zakończeniu drukowania musimy przepłukać PrintStream
.
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.time.LocalDate;
public class FileWritingDemo {
public static void main(String[] args) {
String destination = "file1.txt";
try(PrintStream ps = new PrintStream(destination)){
ps.println("Stackoverflow documentation seems fun.");
ps.println();
ps.println("I love Java!");
ps.printf("Today is: %1$tm/%1$td/%1$tY", LocalDate.now());
ps.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Iteruj po katalogach drukujących w nim katalog
public void iterate(final String dirPath) throws IOException {
final DirectoryStream<Path> paths = Files.newDirectoryStream(Paths.get(dirPath));
for (final Path path : paths) {
if (Files.isDirectory(path)) {
System.out.println(path.getFileName());
}
}
}
Dodawanie katalogów
Aby utworzyć nowy katalog z instancji File
, należy użyć jednej z dwóch metod: mkdirs()
lub mkdir()
.
-
mkdir()
- Tworzy katalog o nazwie tej abstrakcyjnej nazwy ścieżki. ( źródło ) -
mkdirs()
- Tworzy katalog o nazwie tej abstrakcyjnej nazwy ścieżki, w tym wszelkie niezbędne, ale nieistniejące katalogi nadrzędne. Pamiętaj, że jeśli ta operacja się nie powiedzie, być może udało się utworzyć niektóre niezbędne katalogi nadrzędne. ( źródło )
Uwaga: createNewFile()
nie utworzy nowego katalogu tylko plik.
File singleDir = new File("C:/Users/SomeUser/Desktop/A New Folder/");
File multiDir = new File("C:/Users/SomeUser/Desktop/A New Folder 2/Another Folder/");
// assume that neither "A New Folder" or "A New Folder 2" exist
singleDir.createNewFile(); // will make a new file called "A New Folder.file"
singleDir.mkdir(); // will make the directory
singleDir.mkdirs(); // will make the directory
multiDir.createNewFile(); // will throw a IOException
multiDir.mkdir(); // will not work
multiDir.mkdirs(); // will make the directory
Blokowanie lub przekierowywanie standardowego wyjścia / błędu
Czasami źle zaprojektowana biblioteka innej firmy zapisuje niechcianą diagnostykę w strumieniach System.out
lub System.err
. Zalecane rozwiązania tego problemu to znalezienie lepszej biblioteki lub (w przypadku oprogramowania typu open source) rozwiązanie problemu i przesłanie łatki dla programistów.
Jeśli powyższe rozwiązania nie są możliwe, powinieneś rozważyć przekierowanie strumieni.
Przekierowanie w wierszu poleceń
W systemie UNIX, Linux lub MacOSX można to zrobić z powłoki za pomocą >
przekierowania. Na przykład:
$ java -jar app.jar arg1 arg2 > /dev/null 2>&1
$ java -jar app.jar arg1 arg2 > out.log 2> error.log
Pierwszy przekierowuje standardowe wyjście i standardowy błąd do „/ dev / null”, co odrzuca wszystko, co zapisano w tych strumieniach. Drugi przekierowuje standardowe wyjście do „out.log”, a standardowy błąd do „error.log”.
(Aby uzyskać więcej informacji na temat przekierowania, zapoznaj się z dokumentacją używanej powłoki poleceń. Podobne porady dotyczą systemu Windows).
Alternatywnie można zaimplementować przekierowanie w skrypcie opakowania lub pliku wsadowym, który uruchamia aplikację Java.
Przekierowanie w aplikacji Java
Możliwe jest również ponowne wykorzystanie strumieni w aplikacji Java za pomocą System.setOut()
i System.setErr()
. Na przykład poniższy fragment przekierowuje standardowe dane wyjściowe i standardowy błąd do 2 plików dziennika:
System.setOut(new PrintStream(new FileOutputStream(new File("out.log"))));
System.setErr(new PrintStream(new FileOutputStream(new File("err.log"))));
Jeśli chcesz całkowicie wyrzucić dane wyjściowe, możesz utworzyć strumień wyjściowy, który „zapisuje” niepoprawny deskryptor pliku. Jest to funkcjonalnie równoważne pisaniu do „/ dev / null” w systemie UNIX.
System.setOut(new PrintStream(new FileOutputStream(new FileDescriptor())));
System.setErr(new PrintStream(new FileOutputStream(new FileDescriptor())));
Uwaga: setOut
ostrożność podczas używania setOut
i setErr
:
- Przekierowanie wpłynie na całą JVM.
- W ten sposób pozbawiasz użytkownika możliwości przekierowania strumieni z wiersza poleceń.
Dostęp do zawartości pliku ZIP
FileSystem API Java 7 pozwala czytać i dodawać wpisy z lub do pliku Zip za pomocą interfejsu API pliku Java NIO w taki sam sposób, jak na dowolnym innym systemie plików.
FileSystem to zasób, który powinien zostać poprawnie zamknięty po użyciu, dlatego należy użyć bloku try-with-resources.
Odczytywanie z istniejącego pliku
Path pathToZip = Paths.get("path/to/file.zip");
try(FileSystem zipFs = FileSystems.newFileSystem(pathToZip, null)) {
Path root = zipFs.getPath("/");
... //access the content of the zip file same as ordinary files
} catch(IOException ex) {
ex.printStackTrace();
}
Tworzenie nowego pliku
Map<String, String> env = new HashMap<>();
env.put("create", "true"); //required for creating a new zip file
env.put("encoding", "UTF-8"); //optional: default is UTF-8
URI uri = URI.create("jar:file:/path/to/file.zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Path newFile = zipFs.getPath("/newFile.txt");
//writing to file
Files.write(newFile, "Hello world".getBytes());
} catch(IOException ex) {
ex.printStackTrace();
}