
com.mgmtp.perfload.perfalyzer.util.IoUtilities Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2013-2015 mgm technology partners GmbH
*
* 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.mgmtp.perfload.perfalyzer.util;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.SystemUtils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Enumeration;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.get;
import static org.apache.commons.io.FileUtils.copyFile;
import static org.apache.commons.io.FilenameUtils.normalize;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.substringAfter;
/**
* Utility class for IO operations.
*
* @author rnaegele, ctchinda
*/
public class IoUtilities {
private static final int BUFFER_SIZE = 64 * 1024;
private IoUtilities() {
}
/**
* Copies the content from one channel to another.
*
* @param srcChannel
* the source channel to copy from
* @param destChannel
* the destination channel to copy to
*/
public static void copy(final ReadableByteChannel srcChannel, final WritableByteChannel destChannel) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
while (srcChannel.read(buffer) != -1) {
// flip the buffer so it can be written to the destination channel
buffer.flip();
// write to the destination channel
destChannel.write(buffer);
// If partial transfer, shift remainder down so it does not get lost
// If buffer is empty, this is the same as calling clear()
buffer.compact();
}
// EOF will leave buffer in fill state
buffer.flip();
// make sure the buffer is fully drained
while (buffer.hasRemaining()) {
destChannel.write(buffer);
}
}
/**
* Merges a list of files into a single one by appending the contents of each file. If
* {@code headerLines} is greater than zero, the header from the first file is written to the
* destination file. The same number of lines is skipped in all other file, i. e. all files are
* expected to have the same header.
*
* @param sourceFiles
* the list of source files
* @param destFile
* the destination file
* @param headerLines
* the number of header lines
* @param charset
* the character set to use
*/
public static void merge(final File sourceDir, final List sourceFiles, final File destFile,
final int headerLines, final Charset charset) throws IOException {
Files.createParentDirs(destFile);
// simply copy the first file
copyFile(new File(sourceDir, get(sourceFiles, 0).getFile().getPath()), destFile);
if (sourceFiles.size() > 1) {
// append all other files skipping headers
try (Writer w = Files.newWriter(destFile, charset)) {
for (PerfAlyzerFile paf : sourceFiles.subList(1, sourceFiles.size())) {
try (BufferedReader br = Files.newReader(new File(sourceDir, paf.getFile().getPath()), charset)) {
// skip headers
for (int i = 0; i < headerLines; ++i) {
br.readLine();
}
// copy the rest
CharStreams.copy(br, w);
}
}
}
}
}
/**
* Unzips a zip file.
*
* @param zip
* the zip file
* @param destDir
* the destination directory (will be created if non-existent)
*/
public static void unzip(final ZipFile zip, final File destDir) throws IOException {
if (!destDir.exists()) {
destDir.mkdir();
}
for (Enumeration extends ZipEntry> zipEntryEnum = zip.entries(); zipEntryEnum.hasMoreElements(); ) {
ZipEntry zipEntry = zipEntryEnum.nextElement();
extractEntry(zip, zipEntry, destDir);
}
}
private static void extractEntry(final ZipFile zf, final ZipEntry entry, final File destDir) throws IOException {
File file = new File(destDir, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
new File(file.getParent()).mkdirs();
try (InputStream is = zf.getInputStream(entry); FileOutputStream os = new FileOutputStream(file)) {
copy(Channels.newChannel(is), os.getChannel());
}
// preserve modification time; must be set after the stream is closed
file.setLastModified(entry.getTime());
}
}
public static void writeToChannel(final WritableByteChannel destChannel, final ByteBuffer buffer) {
try {
// write to the destination channel
destChannel.write(buffer);
// If partial transfer, shift remainder down so it does not get lost
// If buffer is empty, this is the same as calling clear()
buffer.compact();
// EOF will leave buffer in fill state
buffer.flip();
// make sure the buffer is fully drained
while (buffer.hasRemaining()) {
destChannel.write(buffer);
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
public static void writeLineToChannel(final WritableByteChannel destChannel, final String line, final Charset charset) {
try {
String tmpLine = line.endsWith(SystemUtils.LINE_SEPARATOR) ? line : line + SystemUtils.LINE_SEPARATOR;
CharBuffer buffer = CharBuffer.wrap(tmpLine);
CharsetEncoder encoder = charset.newEncoder();
ByteBuffer bb = encoder.encode(buffer);
writeToChannel(destChannel, bb);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
/**
* Reads the last line of the specified file.
*
* @param file
* the file
* @param charset
* the charset
*/
public static String readLastLine(final File file, final Charset charset) {
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
long length = raf.length() - 1;
ByteArrayOutputStream baos = new ByteArrayOutputStream(80);
for (long pos = length; pos != -1; --pos) { // we start from the end of the file
raf.seek(pos);
int readByte = raf.readByte();
if (readByte == 10) { // this is the case if the file ends with a line-break
if (pos == length) {
continue;
}
break;
} else if (readByte == 13) { // this is the case if the file ends with a line-break (Windows only)
if (pos == length - 1) {
continue;
}
break;
}
baos.write(readByte);
}
byte[] bytes = baos.toByteArray();
// reverse array because it was filled backwards
ArrayUtils.reverse(bytes);
// turn into string respecting the charset
return new String(bytes, charset);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
/**
* Normalizes the specified file using {@link FilenameUtils#normalize(String)}. If {@code file}
* is a directory, the normalized result always ends with the file separator.
*
* @param file
* the file to normalize
* @return the normalized file path
*/
public static String computeNormalizedPath(final File file) throws IOException {
String normalizedPath = normalize(file.getCanonicalPath());
if (file.isDirectory()) {
normalizedPath = ensureEndsWithFileSeparator(normalizedPath);
}
return normalizedPath;
}
/**
* Returns the specified path appending a file separator is necessary.
*
* @param path
* the path
* @return the path ending with a file separator
*/
public static String ensureEndsWithFileSeparator(final String path) {
if (!path.endsWith(SystemUtils.FILE_SEPARATOR)) {
return path + SystemUtils.FILE_SEPARATOR;
}
return path;
}
/**
* Turns the specified file into one relative to the specified parent directory.
*
* @param parentDir
* the parent directory
* @param file
* the file to make relative
* @return the file relative to {@code parentDir}
* @throws IllegalStateException
* if {@code parentDir} is neither a directory nor a parent directory of
* {@code file}
*/
public static File makeRelative(final File parentDir, final File file) {
try {
checkState(parentDir.isDirectory(), "'%s' is not a directory", parentDir);
String normalizedBaseDirPath = computeNormalizedPath(parentDir);
String normalizedFilePath = computeNormalizedPath(file);
String relativeFilePath = substringAfter(normalizedFilePath, normalizedBaseDirPath);
checkState(isNotEmpty(relativeFilePath), "'%s' is not the parent directory of '%s'", parentDir, file);
return new File(relativeFilePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Creates a temporary directory named with a random UUID in the directory specified by the
* system property {@coe java.io.tmpdir}.
*
* @return the directory
*/
public static File createTempDir() {
File file = new File(SystemUtils.JAVA_IO_TMPDIR, UUID.randomUUID().toString());
checkState(file.mkdir(), "Could not create temporary directory %s", file);
return file;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy