我应该关闭 FileChannel 吗?

发布于 2024-12-14 14:53:40 字数 2047 浏览 5 评论 0原文

我今天遇到了我们的一个实用程序类的问题。它是文件的帮助程序,包含一些静态文件复制例程。以下是提取的相关方法以及测试方法。

问题是有时 setLastModified 调用会失败,返回 false。

在我的 PC(Windows 7,最新的 Java)上,我有时会收到“setLastModified failed”消息(大约 1000 次中有 25 次)。

我现在已经通过删除 FileChannel.close 调用解决了这个问题,但我更愿意了解为什么会发生这种情况,即使这是正确的解决方案。

还有其他人遇到同样的问题吗?

private void testCopy() throws FileNotFoundException, IOException {
  File src = new File("C:\\Public\\Test-Src.txt");
  File dst = new File("C:\\Public\\Test-Dst.txt");

  for (int i = 0; i < 1000; i++) {
    copyFile(src, dst);
  }
}

public static void copyFile(final File from, final File to) throws FileNotFoundException, IOException {
  final String tmpName = to.getAbsolutePath() + ".tmp";
  // Copy to a .tmp file.
  final File tmp = new File(tmpName);
  // Do the transfer.
  transfer(from, tmp);
  // Preserve time.
  if (!tmp.setLastModified(from.lastModified())) {
    System.err.println("setLastModified failed!");
  }
  // In case there's one there already.
  to.delete();
  // Rename it in.
  tmp.renameTo(to);
}

public static void transfer(final File from, final File to) throws IOException {
  FileInputStream in = null;
  FileOutputStream out = null;
  try {
    in = new FileInputStream(from);
    out = new FileOutputStream(to);
    transfer(in, out);
  } finally {
    if (null != in) {
      in.close();
    }
    if (null != out) {
      out.close();
    }
  }
}

public static void transfer(final FileInputStream from, final FileOutputStream to) throws IOException {
  FileChannel srcChannel = null;
  FileChannel dstChannel = null;
  //try {
    srcChannel = from.getChannel();
    dstChannel = to.getChannel();
    srcChannel.transferTo(0, srcChannel.size(), dstChannel);
  //} finally {
  //  if (null != dstChannel) {
  //    dstChannel.close();
  //  }
  //  if (null != srcChannel) {
  //    srcChannel.close();
  //  }
  }
}

编辑:我已将代码更改为仅关闭 Streams 而不是 FileChannel,因为研究建议关闭 FileChannel code> 还会关闭 Stream

I came across an issue with one of our utility classes today. It is a helper for files and contains some static file copy routines. Below are the relevant methods extracted along with a test method.

The problem is that sometimes the setLastModified call fails, returning false.

On my PC (Windows 7, latest Java) I sometimes get the "setLastModified failed" message (About 25 times out of 1000).

I have worked around the problem right now by removing the FileChannel.close calls but I would much prefer to understand why this is happening, even if that is the correct solution.

Does anyone else get the same problem?

private void testCopy() throws FileNotFoundException, IOException {
  File src = new File("C:\\Public\\Test-Src.txt");
  File dst = new File("C:\\Public\\Test-Dst.txt");

  for (int i = 0; i < 1000; i++) {
    copyFile(src, dst);
  }
}

public static void copyFile(final File from, final File to) throws FileNotFoundException, IOException {
  final String tmpName = to.getAbsolutePath() + ".tmp";
  // Copy to a .tmp file.
  final File tmp = new File(tmpName);
  // Do the transfer.
  transfer(from, tmp);
  // Preserve time.
  if (!tmp.setLastModified(from.lastModified())) {
    System.err.println("setLastModified failed!");
  }
  // In case there's one there already.
  to.delete();
  // Rename it in.
  tmp.renameTo(to);
}

public static void transfer(final File from, final File to) throws IOException {
  FileInputStream in = null;
  FileOutputStream out = null;
  try {
    in = new FileInputStream(from);
    out = new FileOutputStream(to);
    transfer(in, out);
  } finally {
    if (null != in) {
      in.close();
    }
    if (null != out) {
      out.close();
    }
  }
}

public static void transfer(final FileInputStream from, final FileOutputStream to) throws IOException {
  FileChannel srcChannel = null;
  FileChannel dstChannel = null;
  //try {
    srcChannel = from.getChannel();
    dstChannel = to.getChannel();
    srcChannel.transferTo(0, srcChannel.size(), dstChannel);
  //} finally {
  //  if (null != dstChannel) {
  //    dstChannel.close();
  //  }
  //  if (null != srcChannel) {
  //    srcChannel.close();
  //  }
  }
}

Edit: I have changed the code to only close the Streamss and not the FileChannels because research suggests closing the FileChannel also closes the Stream.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饮湿 2024-12-21 14:53:40

经过对保存 java 库源的各个站点进行一些研究后,看起来非常像 FileChannel.close 最终调用 FileInputStream.closeFileOutputStream.close > 其父对象。

这对我来说意味着您应该关闭 FileChannel 或 Stream,但不能同时关闭

鉴于此,我正在更改原来的帖子以反映一种正确的方法,即关闭Stream而不是Channel

After some research amongst the various sites that hold java library sources it looks very much like FileChannel.close ultimately calls the FileInputStream.close or FileOutputStream.close of its parent object.

This suggests to me that you should either close the FileChannel or the Stream but not both.

In view of this I am changing my original post to reflect one correct method, i.e. close the Streams not the Channels.

染柒℉ 2024-12-21 14:53:40

如果您使用的是 Java 7,则可以使用 Files.copy(路径源、路径目标、CopyOption...选项)为此操作以避免编写、测试和调试您自己的实现。

或者,考虑使用外部库,例如 Apache Commons IO。具体来说,您会发现 FileUtils.copyFile(File srcFile, File destFile) 有趣:

/** 
 * Copies a file to a new location preserving the file date.
 * [...]
 * @param srcFile  an existing file to copy, must not be <code>null</code>
 * @param destFile  the new file, must not be <code>null</code>
 * [...]
 */
public static void copyFile(File srcFile, File destFile) throws IOException

If you are using Java 7, you could use Files.copy(Path source, Path target, CopyOption... options) for this operation to avoid writing, testing and debugging your own implementation.

Alternatively, consider using an external library such as Apache Commons IO. Specifically, you will find FileUtils.copyFile(File srcFile, File destFile) interesting:

/** 
 * Copies a file to a new location preserving the file date.
 * [...]
 * @param srcFile  an existing file to copy, must not be <code>null</code>
 * @param destFile  the new file, must not be <code>null</code>
 * [...]
 */
public static void copyFile(File srcFile, File destFile) throws IOException
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文