<commit_before>/*
 * Copyright 2016 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.matthewtamlin.android_utilities_library.helpers;

import android.content.res.AssetManager;
import android.util.Log;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Utilities for working with assets.
 */
public abstract class AssetsHelper {
	/**
	 * Used during debugging to identify this class.
	 */
	private static final String TAG = "[AssetsHelper]";

	/**
	 * Copies files from assets to another directory.
	 *
	 * @param assetManager
	 * 		an instance of the asset manager for the files to transfer
	 * @param assetFiles
	 * 		the filenames of the files to transfer
	 * @param targetDirectory
	 * 		the directory to copy the files to
	 * @throws IOException
	 * 		if a general IO based error occurs while copying the files
	 */
	public static void copyAssetsToDirectory(final AssetManager assetManager, String[] assetFiles,
			final File targetDirectory) throws IOException {
		if (assetFiles != null) {
			for (String filename : assetFiles) {
				InputStream fromAssets = null;
				OutputStream toTargetDirectory = null;

				try {
					File outFile = new File(targetDirectory, filename);
					toTargetDirectory = new FileOutputStream(outFile);
					fromAssets = assetManager.open(filename);
					copyFile(fromAssets, toTargetDirectory);
				} finally {
					closeStream(fromAssets);
					closeStream(toTargetDirectory);
				}
			}
		}
	}

	/**
	 * Copies a file from the source stream to the target stream.
	 *
	 * @param source
	 * 		the source of the data to copy
	 * @param target
	 * 		the target to copy data to
	 * @throws IOException
	 * 		if a general IO based error occurs while transferring data
	 */
	private static void copyFile(final InputStream source, final OutputStream target) throws
			IOException {
		// Data is moved from the input stream to the output stream through buffer
		byte[] buffer = new byte[1024];

		// Read data into the buffer from the input stream
		int numberOfBytesRead = source.read(buffer);

		// if there was data received, write data to the output stream from the butter
		while (numberOfBytesRead != -1) {
			target.write(buffer, 0, numberOfBytesRead);
			numberOfBytesRead = source.read(buffer);
		}
	}

	/**
	 * Closes a stream. Any any IOExceptions which occur are logged.
	 *
	 * @param stream
	 * 		the stream to close
	 */
	private static void closeStream(Closeable stream) {
		if (stream != null) {
			try {
				stream.close();
			} catch (IOException e) {
				Log.e(TAG, "[Error closing stream] [Stack trace: " + e.getStackTrace() + "]");
			}<commit_msg>Updated AssetsHelper.java<commit_after>/*
 * Copyright 2016 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.matthewtamlin.android_utilities_library.helpers;

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Helper class for copying asset files to a storage directory.
 */
public class AssetsHelper {
	/**
	 * Used during debugging to identify this class.
	 */
	@SuppressWarnings("unused")
	private static final String TAG = "[AssetsHelper]";

	/**
	 * Copies specified asset resources to the supplied directory.
	 *
	 * @param context
	 * 		the Context containing the assets to copy, not null
	 * @param assetFiles
	 * 		the filenames of the asset files to copy, not null
	 * @param targetDirectory
	 * 		the directory to copy the asset files to, not null
	 * @throws IOException
	 * 		if a general IO based error occurs while copying the files
	 * @throws IllegalArgumentException
	 * 		if either {@code context}, {@code assetFiles} or {@code targetDirectory} is null
	 */
	public static void copyAssetsToDirectory(final Context context, final String[] assetFiles,
			final File targetDirectory) throws IOException {
		if (context == null) {
			throw new IllegalArgumentException("context cannot be null");
		} else if (assetFiles == null) {
			throw new IllegalArgumentException("assetFiles cannot be null");
		} else if (targetDirectory == null) {
			throw new IllegalArgumentException("targetDirectory cannot be null");
		}

		final AssetManager assetManager = context.getAssets();

		for (final String filename : assetFiles) {
			// Create a new file in the output directory to receive the asset data
			final File fileInTargetDirectory = new File(targetDirectory, filename);

			// Initialise streams outside of try block so that they can be closed later
			InputStream streamFromAssets = null;
			OutputStream streamToTargetFile = null;

			try {
				// IOExceptions may be thrown
				streamToTargetFile = new FileOutputStream(fileInTargetDirectory);
				streamFromAssets = assetManager.open(filename);
				copyFile(streamFromAssets, streamToTargetFile);
			} finally {
				// An IOException is probably unrecoverable so just abort and close the streams
				closeStream(streamFromAssets);
				closeStream(streamToTargetFile);
			}
		}
	}

	/**
	 * Copies a file from the source stream to the target stream.
	 *
	 * @param source
	 * 		the source of the data to copy, not null
	 * @param target
	 * 		the target to copy data to, not null
	 * @throws IOException
	 * 		if a general IO based error occurs while transferring data
	 * @throws IllegalArgumentException
	 * 		if either {@code source} or {@code target} is null
	 */
	private static void copyFile(final InputStream source, final OutputStream target) throws
			IOException {
		if (source == null) {
			throw new IllegalArgumentException("source cannot be null");
		} else if (target == null) {
			throw new IllegalArgumentException("target cannot be null");
		}

		// Data is moved from the input stream to the output stream through buffer
		final byte[] buffer = new byte[1024];

		// Read data into the buffer from the source
		int numberOfBytesRead = source.read(buffer);

		// If the buffer received data, write data from the buffer to the output stream
		while (numberOfBytesRead != -1) {
			target.write(buffer, 0, numberOfBytesRead);
			numberOfBytesRead = source.read(buffer); // read the next "lot" of data
		}
	}

	/**
	 * Closes a stream. Exceptions are logged if the stream cannot be closed.
	 *
	 * @param stream
	 * 		the stream to close, not null
	 * @throws IllegalArgumentException
	 * 		if {@code stream} is null
	 */
	private static void closeStream(final Closeable stream) {
		if (stream == null) {
			throw new IllegalArgumentException("stream cannot be null");
		}

		try {
			stream.close();
		} catch (IOException e) {
			Log.e(TAG, "[Error closing stream: " + stream + "]", e);
{'fraction_non_alphanumeric': 0.08352373698908352, 'fraction_numerical': 0.003554201574003554, 'mean_word_length': 3.6759643916913944, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3961468', 'n_tokens_mistral': 2345, 'n_tokens_neox': 2067, 'n_words': 871}