Read binary files in java

Reading and Writing Files in Java

One of the most common tasks while creating a software application is to read and write data to a file. The data could be stored in a JSON file, a CSV file, a binary file, or in a text file.

In this article, you’ll learn how to read and write text and binary files in Java. Java provides several APIs (unknown as Java I/O) for reading and writing files right from the beginning. Over the years, these APIs are further improved to provide a simplified and robust interface for dealing with different kinds of files.

If you want to read a simple text file, just use the FileReader class and wrap it in a BufferedReader . Here is an example that uses the BufferedReader class to read a file named input.txt line by line:

try  // create a reader BufferedReader br = new BufferedReader(new FileReader("input.txt")); // read until end of file String line; while ((line = br.readLine()) != null)  System.out.println(line); > // close the reader br.close(); > catch (IOException ex)  ex.printStackTrace(); > 

If you want to read a binary file or a file containing special characters, you need to use the FileInputStream class instead of FileReader . Here is an example:

try  // create a reader FileInputStream fis = new FileInputStream(new File("input.dat")); // read until end of file int ch; while ((ch = fis.read()) != -1)  System.out.print((char) ch); > // close the reader fis.close(); > catch (IOException ex)  ex.printStackTrace(); > 

To write a text file in Java, you should use the FileWriter class and wrap it in a BufferedWriter as shown below:

try  // create a writer BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); // write text to file bw.write("Hey, there!"); bw.newLine(); bw.write("See you soon."); // close the writer bw.close(); > catch (IOException ex)  ex.printStackTrace(); > 

You can easily create and write to a binary file in Java by using the FileOutputStream class. Here is an example that creates a new binary file and writes data into it:

try  // create a writer FileOutputStream fos = new FileOutputStream(new File("output.dat")); // write data to file fos.write("Hey, there!".getBytes()); fos.write("\n".getBytes()); fos.write("See you soon.".getBytes()); // close the writer fos.close(); > catch (IOException ex)  ex.printStackTrace(); > 

You might also like.

Источник

How to Read and Write Binary Files in Java

In this Java File IO tutorial, we show you how to read and write binary files using both legacy File I/O API and new File I/O API (NIO). The legacy API (classes in the java.io.* package) is perfect for manipulating low-level binary I/O operations such as reading and writing exactly one byte at a time, whereas the NIO API (classes in the java.nio.* package) is more convenient for reading and writing the whole file at once, and of course, faster than the old File I/O API.

1. Understanding Byte Streams

We use byte streams to read and write data in binary format, exactly 8-bit bytes. All byte stream classes are descended from the abstract classes InputStream and OutputStream . The following class diagram depicts the main classes in the legacy File I/O API that are designed for working with binary files:

Byte Streams API

You can notice that these classes implement the AutoCloseable interface, which means that we can use the try-with-resources structure to close these streams automatically.

At the top of the hierarchy, the abstract class InputStream defines two primary methods for reading bytes from an input stream:

  • read() : reads one byte of data, returns the byte as an integer value. Return -1 if the end of the file is reached.
  • read(byte[]) : reads a chunk of bytes to the specified byte array, up to the size of the array. This method returns -1 if there’s no more data or the end of the file is reached.

Similarly, the abstract class OutputStream defines two primary methods for writing bytes to an output stream:

  • write(int) : writes the specified byte to the output stream.
  • write(byte[]) : writes the specified array of bytes to the output stream.

Moving down, the implementation classes FileInputStream and FileOutputStream are for reading and writing streams of raw bytes, one or multiple bytes at a time. Whereas the BufferedInputStream and BufferedOutputStream are more efficient by buffering the input stream and output stream to reduce the number of calls to the native API.

Now, let’s see some code examples.

2. Reading and Writing Binary Files Using FileInputStream and FileOutputStream

The following examples use the FileInputStream and FileOutputStream classes to perform low level binary I/O.

This program copies one file to another, one byte at a time. The source file and destination file are provided from command line’s arguments:

import java.io.*; /** * Copy one file to another using low level byte streams, one byte at a time. * @author www.codejava.net */ public class CopyFiles < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < int byteRead = -1; while ((byteRead = inputStream.read()) != -1) < outputStream.write(byteRead); >> catch (IOException ex) < ex.printStackTrace(); >> >
java CopyFiles Project.zip Project1(1).zip

And the following program runs faster because it reads the whole input file into an array of bytes and then write the whole array of bytes to the output file:

import java.io.*; /** * Copy one file to another using low level byte streams, * read and write a whole.at once. * @author www.codejava.net */ public class CopyFilesOne < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < long fileSize = new File(inputFile).length(); byte[] allBytes = new byte[(int) fileSize]; int bytesRead = inputStream.read(allBytes); outputStream.write(allBytes, 0, bytesRead); >catch (IOException ex) < ex.printStackTrace(); >> >

And the following program runs much faster by copying a chunk of bytes at a time (exactly 4096 bytes at a time):

import java.io.*; /** * Copy one file to another using low level byte streams, 4KB at a time. * @author www.codejava.net */ public class CopyFilesChunk < private static final int BUFFER_SIZE = 4096; // 4KB public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try ( InputStream inputStream = new FileInputStream(inputFile); OutputStream outputStream = new FileOutputStream(outputFile); ) < byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) < outputStream.write(buffer, 0, bytesRead); >> catch (IOException ex) < ex.printStackTrace(); >> >

The following program reads the first 8 bytes of a file to identify if it is a PNG image format or not:

import java.io.*; /** * This program checks whether a file is of PNG image format or not, * by analysing its first 8 bytes. * @author www.codejava.net */ public class CheckPNG < private static int[] pngSignature = ; public static void main(String[] args) < if (args.length < 1) < System.out.println("Please provide the input file"); System.exit(0); >String inputFile = args[0]; try ( InputStream inputStream = new FileInputStream(inputFile); ) < int[] headerBytes = new int[8]; boolean isPNG = true; for (int i = 0; i < 8; i++) < headerBytes[i] = inputStream.read(); if (headerBytes[i] != pngSignature[i]) < isPNG = false; break; >> System.out.println("Is PNG file? " + isPNG); > catch (IOException ex) < ex.printStackTrace(); >> >

As you can see, using FileInputStream and FileOutputStream is really good for low level binary I/O such as analyzing a file or even create your own file format.

3. Reading and Writing Binary Files Using BufferedInputStream and BufferedOutputStream

Using BufferedInputStream and BufferedOutputStream is as same as FileInputStream and FileOutputStream . The only difference is that a buffered stream uses an array of byte internally to buffer the input and output to reduce the number of calls to the native API, hence increasing IO performance.

By default, both BufferedInputStream and BufferedOutputStream has an internal buffer of 8192 bytes (8KB), but we can specify a custom buffer size at initialization.

All the above examples can be re-written using buffered streams just by changing the instantiation of the streams. Here’s an example:

try ( InputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile)); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile)); ) < byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) < outputStream.write(buffer, 0, bytesRead); >> catch (IOException ex)

int bufferSize = 16384; // 16KB buffer size InputStream inputStream = new BufferedInputStream(new FileInputStream(inputFile), bufferSize); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile), bufferSize);

4. Reading and Writing Binary Files Using New File I/O API (NIO)

The utility class Files in the java.nio.file package provides the following methods for reading and writing binary data:

  • readAllBytes(Path path) : reads all bytes from a file and returns an array of bytes. This method is intended for reading small files, not large ones.
  • write(Path path, byte[] bytes, OpenOption. options) : writes an array of bytes to a file with some useful options like CREATE, TRUNCATE_EXISTING, WRITE and APPEND.

Let’s see an example. The files copy program above can be re-written using NIO API like this:

import java.io.*; import java.nio.file.*; /** * Copy one file to another using low level byte streams, one byte at a time. * @author www.codejava.net */ public class CopyFilesNIO < public static void main(String[] args) < if (args.length < 2) < System.out.println("Please provide input and output files"); System.exit(0); >String inputFile = args[0]; String outputFile = args[1]; try < long start = System.currentTimeMillis(); byte[] allBytes = Files.readAllBytes(Paths.get(inputFile)); Files.write(Paths.get(outputFile), allBytes); long end = System.currentTimeMillis(); System.out.println("Copied in " + (end - start) + " ms"); >catch (IOException ex) < ex.printStackTrace(); >> >

Try to run this program and compare the time with the ones using legacy File I/O (on big files) you will see NIO performs much faster.

API References:

Other Java File IO Tutorials:

About the Author:

Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.

Источник

Reading and Writing Binary Files

To open a file for reading, you can use the newInputStream(Path, OpenOption. ) method. This method returns an unbuffered input stream for reading bytes from the file.

Path file = . ; try (InputStream in = Files.newInputStream(file); BufferedReader reader = new BufferedReader(new InputStreamReader(in))) < String line = null; while ((line = reader.readLine()) != null) < System.out.println(line); >> catch (IOException x)

Creating and Writing a File by Using Stream I/O

You can create a file, append to a file, or write to a file by using the newOutputStream(Path, OpenOption. ) method. This method opens or creates a file for writing bytes and returns an unbuffered output stream.

The method takes an optional OpenOption parameter. If no open options are specified, and the file does not exist, a new file is created. If the file exists, it is truncated. This option is equivalent to invoking the method with the CREATE and TRUNCATE_EXISTING options.

The following example opens a log file. If the file does not exist, it is created. If the file exists, it is opened for appending.

import static java.nio.file.StandardOpenOption.*; import java.nio.file.*; import java.io.*; public class LogFileTest < public static void main(String[] args) < // Convert the string to a // byte array. String s = "Hello World! "; byte data[] = s.getBytes(); Path p = Paths.get("./logfile.txt"); try (OutputStream out = new BufferedOutputStream( Files.newOutputStream(p, CREATE, APPEND))) < out.write(data, 0, data.length); >catch (IOException x) < System.err.println(x); >> > 

Reading and Writing Files by Using Channel I/O

While stream I/O reads a character at a time, channel I/O reads a buffer at a time. The ByteChannel interface provides basic read and write functionality. A SeekableByteChannel is a ByteChannel that has the capability to maintain a position in the channel and to change that position. A SeekableByteChannel also supports truncating the file associated with the channel and querying the file for its size.

The capability to move to different points in the file and then read from or write to that location makes random access of a file possible. See the section Random Access Files for more information.

There are two methods for reading and writing channel I/O.

Note: The newByteChannel() methods return an instance of a SeekableByteChannel . With a default file system, you can cast this seekable byte channel to a FileChannel providing access to more advanced features such mapping a region of the file directly into memory for faster access, locking a region of the file so other processes cannot access it, or reading and writing bytes from an absolute position without affecting the channel’s current position.

Both newByteChannel() methods enable you to specify a list of OpenOption options. The same open options used by the newOutputStream() methods are supported, in addition to one more option: READ is required because the SeekableByteChannel supports both reading and writing.

Specifying READ opens the channel for reading. Specifying WRITE or APPEND opens the channel for writing. If none of these options are specified, then the channel is opened for reading.

The following code snippet reads a file and prints it to standard output:

public static void readFile(Path path) throws IOException < // Files.newByteChannel() defaults to StandardOpenOption.READ try (SeekableByteChannel sbc = Files.newByteChannel(path)) < final int BUFFER_CAPACITY = 10; ByteBuffer buf = ByteBuffer.allocate(BUFFER_CAPACITY); // Read the bytes with the proper encoding for this platform. If // you skip this step, you might see foreign or illegible // characters. String encoding = System.getProperty("file.encoding"); while (sbc.read(buf) >0) < buf.flip(); System.out.print(Charset.forName(encoding).decode(buf)); buf.clear(); >> > 

The following example, written for UNIX and other POSIX file systems, creates a log file with a specific set of file permissions. This code creates a log file or appends to the log file if it already exists. The log file is created with read/write permissions for owner and read only permissions for group.

import static java.nio.file.StandardOpenOption.*; import java.nio.*; import java.nio.channels.*; import java.nio.file.*; import java.nio.file.attribute.*; import java.io.*; import java.util.*; public class LogFilePermissionsTest < public static void main(String[] args) < // Create the set of options for appending to the file. Setoptions = new HashSet(); options.add(APPEND); options.add(CREATE); // Create the custom permissions attribute. Set perms = PosixFilePermissions.fromString("rw-r-----"); FileAttribute attr = PosixFilePermissions.asFileAttribute(perms); // Convert the string to a ByteBuffer. String s = "Hello World! "; byte data[] = s.getBytes(); ByteBuffer bb = ByteBuffer.wrap(data); Path file = Paths.get("./permissions.log"); try (SeekableByteChannel sbc = Files.newByteChannel(file, options, attr)) < sbc.write(bb); >catch (IOException x) < System.out.println("Exception thrown: " + x); >> > 

Источник

Читайте также:  Питон массивы для начинающих
Оцените статью