Mercurial > hg4j
view src/org/tmatesoft/hg/internal/FileUtils.java @ 619:868b2ffdcd5c
Close FIS, not FileChannel, to clear both references to FileDescriptor right away
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 17 May 2013 22:04:23 +0200 |
parents | 7c0d2ce340b8 |
children | 507602cb4fb3 |
line wrap: on
line source
/* * Copyright (c) 2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For information on how to redistribute this software under * the terms of a license other than GNU General Public License * contact TMate Software at support@hg4j.com */ package org.tmatesoft.hg.internal; import static org.tmatesoft.hg.util.LogFacility.Severity.Debug; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import org.tmatesoft.hg.core.HgIOException; import org.tmatesoft.hg.util.LogFacility; import org.tmatesoft.hg.util.LogFacility.Severity; /** * * @author Artem Tikhomirov * @author TMate Software Ltd. */ public final class FileUtils { private final LogFacility log; public static void copyFile(File from, File to) throws HgIOException { new FileUtils(new StreamLogFacility(Debug, true, System.err)).copy(from, to); } public FileUtils(LogFacility logFacility) { log = logFacility; } public void copy(File from, File to) throws HgIOException { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream(from); fos = new FileOutputStream(to); FileChannel input = fis.getChannel(); FileChannel output = fos.getChannel(); long count = input.size(); long pos = 0; int zeroCopied = 0; // flag to prevent hang-up do { long c = input.transferTo(pos, count, output); pos += c; count -= c; if (c == 0) { if (++zeroCopied == 3) { String m = String.format("Can't copy %s to %s, transferTo copies 0 bytes. Position: %d, bytes left:%d", from.getName(), to.getName(), pos, count); throw new IOException(m); } } else { // reset zeroCopied = 0; } } while (count > 0); fos.close(); fos = null; fis.close(); fis = null; } catch (IOException ex) { // not in finally because I don't want to loose exception from fos.close() closeQuietly(fis); closeQuietly(fos); String m = String.format("Failed to copy %s to %s", from.getName(), to.getName()); throw new HgIOException(m, ex, from); } } public void closeQuietly(Closeable stream) { if (stream != null) { try { stream.close(); } catch (IOException ex) { // ignore log.dump(getClass(), Severity.Warn, ex, "Exception while closing stream quietly"); } } } public static void main(String[] args) throws Exception { final long start = System.nanoTime(); final File src = new File(".../hg/cpython/.hg/store/00changelog.d"); copyFile(src, new File("/tmp/zxczxczxc234")); final long end = System.nanoTime(); System.out.printf("Copy of %,d bytes took %d ms", src.length(), (end-start)/1000000); } }