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

Java SE 7
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

Java SE 7
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();
}
Java SE 7
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:

Java SE 1.4
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 :

Java SE 7
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:

  1. Potrzebujemy wystąpienia FileInputStream . FileInputStream ma metodę o nazwie getChannel() która zwraca kanał.
  2. Wywołaj getChannel() FileInputStream i getChannel() kanał.
  3. Utwórz ByteBuffer. ByteBuffer jest pojemnikiem o stałej wielkości bajtów.
  4. 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ę
  5. Kiedy wywołujemy metodę odczytu Channel , wypełnia on bufor przy użyciu danych.
  6. 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.
  7. 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:

  1. Najpierw musimy uzyskać obiekt FileOutputStream
  2. Nabywać FileChannel wywołanie getChannel() metodę z FileOutputStream
  3. Utwórz ByteBuffer a następnie wypełnij go danymi
  4. Następnie musimy wywołać metodę flip() ByteBuffer i przekazać ją jako argument metody write() FileChannel
  5. 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 :

  1. Przekierowanie wpłynie na całą JVM.
  2. 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();
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow