在Java 7中删除二进制文件的一部分的最佳方法是什么

Pau*_*lor 6 java nio

即我有一个10 MB的文件,我想删除1M到2M的字节,因此生成的文件是9mb,从文件中以2m字节开始的数据现在从1M开始

我使用Java 7,因此可以制作NIO,文件大小通常为10MB,并且经常通过网络访问,所以我正在寻找一个表现良好的优雅解决方案.

我知道BteBuffer.allocateDirect()和File.getChannel(),但我很难解决,如果有办法做我想要的,不涉及必须从文件通道写入8MB临时缓冲区只是为了写回来在不同的地方存档,或者如果使用allocateDirect()这实际上是可以的

小智 0

我认为使用磁盘上的临时文件的方法是一个好方法。如果您可以在磁盘上创建新的临时文件,那么 nio 确实有一些选项可以帮助您。我只是在这里讨论 API 和 nio 教程,但看起来FileChannel.transferFrom或者FileChannel.transferTo可能是您需要的工具。

我尚未测试以下代码,但它应该为您指明正确的方向。

public static void main(String[] args) {
    int megaByte = 1024 * 1024;
    // prepare the paths
    Path inPath = Paths.get("D:/file.dat"); // java.nio.file.Paths
    Path outPath; // java.nio.file.Path
    try {
        outPath = Files.createTempFile(null, "swp"); // java.nio.file.Files
    } catch (IOException ex) {
        throw new IOError(ex);
    }

    // process the file
    try (
            FileChannel readChannel = new FileChannel.open(inPath, READ);
            FileChannel writeChannel = new FileChannel.open(outPath, WRITE, TRUNCATE_EXISTING)
    ) {
        long readFileSize = readChannel.size();
        long expectedWriteSize = readFileSize;
        if (readFileSize > 2 * megabyte)
            expectedWriteSize = readFileSize - megabyte;
        else if (readFileSize > megabyte)
            expectedWriteSize = megabyte;
        // copy first megabyte (or entire file if less than a megabyte)
        long bytesTrans = readChannel.transferTo(0, megabyte, writeChannel);
        // copy everything after the second megabyte
        if (readFileSize > 2 * megabyte)
            bytesTrans += readChannel.transferTo(2 * megabyte, readFileSize - 2 * megabyte, writeChannel);
        if (bytesTrans != expectedWriteSize)
            System.out.println("WARNING: Transferred " + bytesTrans + " bytes instead of " + expectedWriteSize);
    } catch (FileNotFoundException ex) {
        throw new RuntimeException("File not found!", ex);
    } catch (IOException ex) {
        throw new RuntimeException("Caught IOException", ex);
    }

    // replace the original file with the temporary file
    try {
        // ATOMIC_MOVE may cause IOException here . . .
        Files.move(outPath, inPath, REPLACE_EXISTING, ATOMIC_MOVE);
    } catch (IOException e1) {
        try {
            // . . . so it's probably worth trying again without that option
            Files.move(outPath, inPath, REPLACE_EXISTING);
        } catch (IOException e2) {
            throw new IOError(e2);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

即使您无法打开新文件,nio 也可能会提供帮助。如果您打开一个文件的读/写通道或在同一文件上打开两个不同的通道,则可以使用该方法将文件的一部分传输到文件的另一部分transferTo。我没有足够的经验来了解。API 声明采用显式位置参数(如 的第一个参数)的方法transferTo可以与写入文件的操作同时进行,因此我不会排除它。如果您尝试这样做,您可能希望以兆字节大小的块重写文件。如果这确实有效,那么FileChannel.truncate当您将文件的某些部分写入到文件中较早一兆字节的位置后,可以使用它来截断文件的最后一兆字节。