即我有一个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当您将文件的某些部分写入到文件中较早一兆字节的位置后,可以使用它来截断文件的最后一兆字节。