Showing posts with label outputstream. Show all posts
Showing posts with label outputstream. Show all posts

Sunday, 7 April 2024

Copy InputStream to OutputStream in Java

In Java, copying data from an InputStream to an OutputStream is a common task, especially when dealing with file operations, network communications, or handling HTTP requests. In this blog post, we'll explore efficient methods to perform this operation, discussing best practices and potential pitfalls along the way.

 

Below are several scenarios in which copying an InputStream to an OutputStream is common in Java:

 

1.   Data Forwarding: In situations where you need to transfer data from one stream to another, such as redirecting the output of one program to serve as input for another.

2.   File Persistence: When dealing with an InputStream sourced from a network request or another origin, you may want to replicate its content into a FileOutputStream to persist the data into a file.

3.   Temporary Data Storage: Utilizing a ByteArrayOutputStream, you can duplicate a stream's content into memory temporarily, facilitating subsequent processing operations.

 

Approach 1: Using plain core java InputStream and OutputStream classes.

 

IOStreamUtil1.java

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class IOStreamUtil1 {

	private IOStreamUtil1() {
		// Restrict to create an object to this
	}

	public static final int DEFAULT_BUFFER_SIZE = 8192;

	public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream)
			throws IOException {
		return copy(inputStream, outputStream, closeOutputStream, new byte[DEFAULT_BUFFER_SIZE]);
	}

	public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream,
			byte[] buffer) throws IOException {

		if (inputStream == null) {
			throw new IllegalArgumentException("inputStream is null");
		}

		if (outputStream == null) {
			throw new IllegalArgumentException("outputStream is null");
		}

		try (InputStream in = inputStream) {
			long total = 0;

			int res = -1;

			while ((res = in.read(buffer)) != -1) {
				total += res;
				if (outputStream != null) {
					outputStream.write(buffer, 0, res);
				}
			}

			if (closeOutputStream) {
				outputStream.close();
			} else {
				outputStream.flush();
			}

			return total;
		}
	}
	
	public static void main(String[] args) throws IOException {
		// Create sample input and output streams
        ByteArrayInputStream inputStream = new ByteArrayInputStream("Hello, World!".getBytes());
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        // Test the copy method
        long bytesCopied = copy(inputStream, outputStream, true);

        // Print the result
        System.out.println("Bytes copied: " + bytesCopied);
        System.out.println("Output stream content: " + outputStream.toString());
	}
}

 

Output

Bytes copied: 13
Output stream content: Hello, World!

Approach 2: Using InputStream#transferTo method.

 

public long transferTo(OutputStream out) throws IOException

This method is introduced in Java9. Reads all bytes from this input stream and writes the bytes to the given output stream in the order that they are read. On return, this input stream will be at end of stream. This method does not close either stream. If the total number of bytes transferred is greater than Long.MAX_VALUE, then Long.MAX_VALUE will be returned.

 


IOStreamUtil2.java

 

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class IOStreamUtil2 {

	public static long copy(InputStream inputStream, OutputStream outputStream) throws IOException {

		if (inputStream == null) {
			throw new IllegalArgumentException("inputStream is null");
		}

		if (outputStream == null) {
			throw new IllegalArgumentException("outputStream is null");
		}

		return inputStream.transferTo(outputStream);

	}

	public static void main(String[] args) throws IOException {
		// Create sample input and output streams
		ByteArrayInputStream inputStream = new ByteArrayInputStream("Hello, World!".getBytes());
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

		// Test the copy method
		long bytesCopied = copy(inputStream, outputStream);

		// Print the result
		System.out.println("Bytes copied: " + bytesCopied);
		System.out.println("Output stream content: " + outputStream.toString());
	}
}

Approach 3: Using Apache commons IOUtils.copy method.

 

Apache Commons IO library provides utility methods for working with streams, including copying streams efficiently. Using this library simplifies the code and makes it more readable.

 

public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException

Copies bytes from an InputStream to an OutputStream. Large streams (over 2GB) will return a bytes copied value of -1 after the copy has completed since the correct number of bytes cannot be returned as an int. For large streams use the copyLarge(InputStream, OutputStream) method.

 

IOStreamUtil3.java

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;

public class IOStreamUtil2 {

	public static int copy(InputStream inputStream, OutputStream outputStream) throws IOException {

		if (inputStream == null) {
			throw new IllegalArgumentException("inputStream is null");
		}

		if (outputStream == null) {
			throw new IllegalArgumentException("outputStream is null");
		}

		int noOfBytesopied = IOUtils.copy(inputStream, outputStream);
		return noOfBytesopied;
	}

	public static void main(String[] args) throws IOException {
		// Create sample input and output streams
		ByteArrayInputStream inputStream = new ByteArrayInputStream("Hello, World!".getBytes());
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

		// Test the copy method
		long bytesCopied = copy(inputStream, outputStream);

		// Print the result
		System.out.println("Bytes copied: " + bytesCopied);
		System.out.println("Output stream content: " + outputStream.toString());
	}
}

Approach 4: Using IOUtils.copyLarge method.

public static long copyLarge(final InputStream inputStream, final OutputStream outputStream) throws IOException

public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer)

Copies bytes from a large (over 2GB) InputStream to an OutputStream This method buffers the input internally, so there is no need to use a BufferedInputStream. Default buffer size is 8192 bytes.

 

IOStreamUtil4.java

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;

public class IOStreamUtil3 {

	public static long copy(InputStream inputStream, OutputStream outputStream) throws IOException {

		if (inputStream == null) {
			throw new IllegalArgumentException("inputStream is null");
		}

		if (outputStream == null) {
			throw new IllegalArgumentException("outputStream is null");
		}

		long noOfBytesopied = IOUtils.copyLarge(inputStream, outputStream);
		return noOfBytesopied;
	}

	public static void main(String[] args) throws IOException {
		// Create sample input and output streams
		ByteArrayInputStream inputStream = new ByteArrayInputStream("Hello, World!".getBytes());
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

		// Test the copy method
		long bytesCopied = copy(inputStream, outputStream);

		// Print the result
		System.out.println("Bytes copied: " + bytesCopied);
		System.out.println("Output stream content: " + outputStream.toString());
	}
}

Approach 5: Using Java NIO

Java NIO offers a non-blocking I/O API that can also be used for efficient stream copying. This approach is particularly useful when dealing with large files or when performance is critical.

 

IOStreamUtil5.java

package com.sample.app.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

public class IOStreamUtil4 {

	public static void copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream)
			throws IOException {

		if (inputStream == null) {
			throw new IllegalArgumentException("inputStream is null");
		}

		if (outputStream == null) {
			throw new IllegalArgumentException("outputStream is null");
		}

		try (InputStream inp = inputStream;
				ReadableByteChannel inChannel = Channels.newChannel(inp);
				WritableByteChannel outChannel = Channels.newChannel(outputStream)) {
			ByteBuffer buffer = ByteBuffer.allocateDirect(8192); // 8KB buffer size
			while (inChannel.read(buffer) != -1) {
				buffer.flip();
				outChannel.write(buffer);
				buffer.clear();
			}
		}

		if (closeOutputStream) {
			outputStream.close();
		} else {
			outputStream.flush();
		}

	}

	public static void main(String[] args) throws IOException {
		// Create sample input and output streams
		ByteArrayInputStream inputStream = new ByteArrayInputStream("Hello, World!".getBytes());
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

		// Test the copy method
		copy(inputStream, outputStream, true);

		System.out.println("Output stream content: " + outputStream.toString());
	}
}

Copying data from an InputStream to an OutputStream is a fundamental operation in Java programming. By using buffered streams, leveraging third-party libraries like Apache Commons IO, or utilizing the Java NIO package, you can perform this task efficiently and effectively. Consider your specific requirements, such as performance, resource usage, and code readability, when choosing the appropriate method for copying streams in your Java applications.


 

You may like

file and stream programs in Java

Write InputStream to a file in Java

File separator, separatorChar, pathSeparator, pathSeparatorChar in Java

Implement an Output stream that writes the data to two output streams

Check whether directory can be accessed and has read and write privileges in Java

Get the hash or message digest of a file in Java

Saturday, 10 September 2022

Convert OutputStream to String in Java

‘java.io.OutputStream’  is the abstract superclass of all the classes representing an output stream of bytes. An output stream accepts output bytes and sends them to some sink/destination.

 

Following examples explain how to convert different a ByteArrayOutputStream object to string in Java.

 

Example 1: Convert ByteArrayOutputStream to string.

 

Get the byte array from ByteArrayOutputStream object.

byte[] byteArr = byteArrayOutputStream.toByteArray();

Initialize the string using byte array.

String str2 = new String(byteArr);

Find the below working application.

 

OutputStreamToStringDemo1.java

package com.sample.app.streams;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class OutputStreamToStringDemo1 {

	public static void main(String[] args) throws IOException {
		try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
			String str1 = "Hello World!!!!";
			byteArrayOutputStream.write(str1.getBytes());

			byte[] byteArr = byteArrayOutputStream.toByteArray();
			String str2 = new String(byteArr);

			System.out.println("str1 : " + str1);
			System.out.println("str2 : " + str2);
		}

	}

}

Output

str1 : Hello World!!!!
str2 : Hello World!!!!

Example 2: Using toString method of ByteArrayOutputStream.

ByteArrayOutputString#toString method converts the buffer's contents into a string decoding bytes using the platform's default character set.

String str2 = byteArrayOutputStream.toString();

OutputStreamToStringDemo2.java

package com.sample.app.streams;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class OutputStreamToStringDemo2 {

	public static void main(String[] args) throws IOException {
		try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
			String str1 = "Hello World!!!!";
			byteArrayOutputStream.write(str1.getBytes());

			String str2 = byteArrayOutputStream.toString();

			System.out.println("str1 : " + str1);
			System.out.println("str2 : " + str2);
		}

	}

}

Output

str1 : Hello World!!!!
str2 : Hello World!!!!

You can even set the character set to decode the byte array to string using following toString methods.

public synchronized String toString(Charset charset)

public synchronized String toString(String charsetName)

Converts the buffer's contents into a string by decoding the bytes using the specified charset.

 

An invocation of this method of the form

String str = byteArrayOutputStream.toString("UTF-8");

 

behaves in exactly the same way as the below expression.

String str = byteArrayOutputStream.toString(StandardCharsets.UTF_8);

 


OutputStreamToStringDemo3.java

package com.sample.app.streams;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class OutputStreamToStringDemo3 {

	public static void main(String[] args) throws IOException {
		try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
			String str1 = "Hello World!!!!";
			byteArrayOutputStream.write(str1.getBytes());

			String str2 = byteArrayOutputStream.toString("UTF-8");
			String str3 = byteArrayOutputStream.toString(StandardCharsets.UTF_8);

			System.out.println("str1 : " + str1);
			System.out.println("str2 : " + str2);
			System.out.println("str3 : " + str3);
		}

	}

}

Output

str1 : Hello World!!!!
str2 : Hello World!!!!
str3 : Hello World!!!!



You may like

Copy the content of file to other location

Write byte array to a file

How to download a binary file in Java?

How to process a huge file line by line in Java?

How to get the directory size in Java?

Saturday, 9 July 2022

How to download a binary file in Java?

Approach 1: Using InputStream, we can read the data from the given url and OutputStream can be used to write the binary data to disk.

 


 

Find the below working application.

 

BinaryDownloaderDemo.java

package com.sample.app;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

public class BinaryDownloaderDemo {

	private static void downloadFile(final String urlToDownload, final String filePath) {
		
		// Create parent folders if not exists
		final File file = new File(filePath);
		file.getParentFile().mkdirs();

		try {
			final URL url = new URL(urlToDownload);
			final URLConnection urlConnection = url.openConnection();

			try (final InputStream inputStream = urlConnection.getInputStream();
					final OutputStream outputStream = new FileOutputStream(filePath);) {
				byte[] buffer = new byte[65535];
				int bytesRead;
				while ((bytesRead = inputStream.read(buffer)) != -1) {
					outputStream.write(buffer, 0, bytesRead);
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		final String urlToDownlaod =  "https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.zip";
		
		downloadFile(urlToDownlaod, "/Users/Shared/softwares/maven/apache-maven-3.8.6-bin.zip");
		
	}

}

 

Approach 2: Using nio FileChannel# transferFrom method.

 

BinaryDownloaderDemo2.java

package com.sample.app;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class BinaryDownloaderDemo2 {

	private static void downloadFile(final String urlToDownload, final String filePath) {

		// Create parent folders if not exists
		final File file = new File(filePath);
		file.getParentFile().mkdirs();

		try {
			URL website = new URL(urlToDownload);

			try (ReadableByteChannel rbc = Channels.newChannel(website.openStream());
					FileOutputStream fos = new FileOutputStream(filePath);) {
				fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		final String urlToDownlaod = "https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.zip";

		downloadFile(urlToDownlaod, "/Users/Shared/softwares/maven/apache-maven-3.8.6-bin.zip");

	}

}

 

 

 

You may like

File programs in Java

Count number of lines in a file

Download file from Internet using Java

Get the content of resource file as string

Copy the content of file to other location

Write byte array to a file