首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 8中某些文件替换字节的优化

Java 8中某些文件替换字节的优化
EN

Stack Overflow用户
提问于 2019-11-04 03:02:32
回答 1查看 250关注 0票数 2

我在Java中有这个方法,我想改进它。该方法用于用新字节替换某些File的某个部分(在开头、中间或结尾)(所选部分可以替换为较小或更多字节)。通过位置(start)和quantity完成选择。

我不能使用外部库(guava或其他库)。

这是我的旧代码:

代码语言:javascript
复制
public static void replaceBytesFile(RandomAccessFile rafTarget,
    byte[] replacers, int start, int quantity) {
  //replaces exact amount of bytes of a file starting at a specified position
  RandomAccessFile rafTemp = null;

  //Ini Select a Random NonExistent File
  File userDirectory = new File(System.getProperty("user.dir"));
  File temporalFile;
  boolean existsTemporalFile = false;
  String temporalFilename = "";
  while (!existsTemporalFile) {
    temporalFilename = "File_" + Double.toString(100000 * Math.random()) + ".tmp";
    temporalFilename = userDirectory + MethodGen.FS + temporalFilename;
    temporalFile = new File(temporalFilename);
    if (!temporalFile.exists()) {
      existsTemporalFile = true;
    }
  }
  //End Select a Random NonExistent File
  try {
    rafTemp = new RandomAccessFile(temporalFilename, "rw");
    int workBufferSize = 65536;
    //Ini Copy first (Start - 1) MethodBytes
    int step = workBufferSize;
    int countPosition = 0;
    while (countPosition < start) {
      rafTarget.seek(countPosition);
      rafTemp.seek(countPosition);
      if ((start - countPosition) < step) {
        step = start - countPosition;
      }
      byte[] WorkBuffer = new byte[step];
      rafTarget.read(WorkBuffer);
      rafTemp.write(WorkBuffer);
      countPosition += step;
    }
    //End Copy first (start - 1) MethodBytes
    rafTemp.write(replacers);
    rafTarget.seek(start + quantity);
    int end = (int) rafTarget.length();
    //Ini Copy last MethodBytes
    step = workBufferSize;
    countPosition = start + quantity;
    while (countPosition < end) {
      rafTarget.seek(countPosition);
      rafTemp.seek(countPosition - quantity + replacers.length);
      if ((end - countPosition) <= step) {
        step = end - countPosition;
      }
      byte[] WorkBuffer = new byte[step];
      rafTarget.read(WorkBuffer);
      rafTemp.write(WorkBuffer);
      countPosition += step;
    }
    //End Copy last MethodBytes

    rafTarget.setLength(0);
    step = workBufferSize;
    countPosition = 0;
    end = (int) rafTemp.length();
    //Ini Copy all MethodBytes to original
    while (countPosition < end) {
      rafTemp.seek(countPosition);
      rafTarget.seek(countPosition);
      if ((end - countPosition) <= step) {
        step = end - countPosition;
      }
      byte[] WorkBuffer = new byte[step];

      rafTemp.read(WorkBuffer);
      rafTarget.write(WorkBuffer);
      countPosition += step;
    }
    //End Copy all MethodBytes to original
    rafTemp.close();
    temporalFile = new File(temporalFilename);
    temporalFile.delete();
  } catch (IOException ioe) {
    System.out.println(ioe.toString());
  } finally {
    try {
      if (rafTemp != null) {
        rafTemp.close();
      }
    } catch (IOException e) {
    }
  }
}

我将手动从原始文件复制到执行更改的时态文件,稍后,

我的代码正在工作,但我想知道Java 8(首选)中的一些最好的替代方案。

现在测试怎么样?

代码语言:javascript
复制
  public static void main(String[] args) {
    String originalFilename = "OriginalTraveling.txt";
    String copiedFilename = "TravelingToBeChanged.txt";

    Path copiedPath = Paths.get(copiedFilename);
    Path originalPath = new File(originalFilename).toPath();
    System.out.println("filename:" + originalFilename);

    String contet = "I want to travel to my Country.";
    try {
      RandomAccessFile raf = new RandomAccessFile(originalFilename, "rw");
      putBytesFile(raf, contet.getBytes(), 0);
      Files.copy(originalPath, copiedPath, StandardCopyOption.REPLACE_EXISTING);
    }
    catch (IOException e) {
      System.out.println("Exception caught " + e.toString());
    }


    try {
      RandomAccessFile raf = new RandomAccessFile(copiedFilename, "rw");
      String toBeChanged = "my Country.";
      String toBeInserted = "India, China, Europe, Latin America, Australia.";
      int position = contet.indexOf(toBeChanged);
      replaceBytesFile(raf, toBeInserted.getBytes(), position, toBeChanged.length());
    }
    catch (IOException e) {
      System.out.println("Exception caught " + e.toString());
    }

    try {
      RandomAccessFile raf = new RandomAccessFile(copiedFilename, "rw");
      String replacedContent = new String(getBytesFile(raf, 0, (int) raf.length()));
      String toBeChanged = "Latin America";
      String toBeInserted = "Colombia";
      int position = replacedContent.indexOf(toBeChanged);
      replaceBytesFile(raf, toBeInserted.getBytes(), position, toBeChanged.length());
    } catch (IOException e) {
      System.out.println("Exception caught " + e.toString());
    }
  }

方法让Bytes!

代码语言:javascript
复制
  public static void putBytesFile(RandomAccessFile RAFTarget, byte[] content, int position) {
    int size = content.length;
    try {
      long oldPosition = RAFTarget.getFilePointer();
      if (!((position < 0) || !(size > 0))) {
        RAFTarget.seek(position);
        RAFTarget.write(content);
        RAFTarget.seek(oldPosition);
      }
    } catch (java.io.IOException e) {
      System.out.println(e.toString());
    }
  }

方法获取文件!

代码语言:javascript
复制
  public static byte[] getBytesFile(RandomAccessFile RAFSource, int position, int quantity) {
    byte[] content = null;
    try {
      long oldPosition = RAFSource.getFilePointer();
      if ((position < 0) || !(quantity > 0)) {
        return (content);
      } else {
        if (RAFSource.length() < (position + quantity)) {
          quantity = (int) RAFSource.length() - position;
        }
        RAFSource.seek(position);
        content = new byte[quantity];
        RAFSource.read(content);
        RAFSource.seek(oldPosition);
      }
    } catch (java.io.IOException e) {
      System.out.println(e.toString());
    }
    return content;
  }

OriginalTraveling.txt含量

代码语言:javascript
复制
I want to travel to my Country.

TravelingToBeChanged.txt含量

代码语言:javascript
复制
I want to travel to India, China, Europe, Latin America, Australia.

最后介绍了TravelingToBeChanged.txt的内容。

代码语言:javascript
复制
I want to travel to India, China, Europe, Colombia, Australia.

如果可以注意到,它们不会被更改为相同的字节数。

你知道替代文件内容的其他方法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-04 11:59:23

即使对古老的代码来说,这看起来也是不必要的复杂。

例如,代替

代码语言:javascript
复制
//Ini Select a Random NonExistent File
File userDirectory = new File(System.getProperty("user.dir"));
File temporalFile;
boolean existsTemporalFile = false;
String temporalFilename = "";
while (!existsTemporalFile) {
  temporalFilename = "File_" + Double.toString(100000 * Math.random()) + ".tmp";
  temporalFilename = userDirectory + MethodGen.FS + temporalFilename;
  temporalFile = new File(temporalFilename);
  if (!temporalFile.exists()) {
    existsTemporalFile = true;
  }
}

只管用

代码语言:javascript
复制
File temporalFile = File.createTempFile("File_", ".tmp", userDirectory);

请参阅createTempFile

更进一步,而不是

代码语言:javascript
复制
int step = workBufferSize;
int countPosition = 0;
while (countPosition < start) {
  rafTarget.seek(countPosition);
  rafTemp.seek(countPosition);
  if ((start - countPosition) < step) {
    step = start - countPosition;
  }
  byte[] WorkBuffer = new byte[step];
  rafTarget.read(WorkBuffer);
  rafTemp.write(WorkBuffer);
  countPosition += step;
}

使用

代码语言:javascript
复制
for(int step=workBufferSize, countPosition=0; countPosition < start; countPosition += step){
  rafTarget.seek(countPosition);
  rafTemp.seek(countPosition);
  if ((start - countPosition) < step) {
    step = start - countPosition;
  }
  byte[] WorkBuffer = new byte[step];
  rafTarget.read(WorkBuffer);
  rafTemp.write(WorkBuffer);
}

显然,您有一个初始语句、一个条件和一个增量操作,换句话说,就是一个典型的for循环。这同样适用于另外两个while循环。

然而,使用新的API,事情无论如何要简单得多:

代码语言:javascript
复制
// consider using long for position and Path for the file, unless
// the RandomAccessFile is really needed for other purposes
public static void replaceBytesFile(RandomAccessFile rafTarget,
    byte[] replacers, int start, int quantity) throws IOException {

    // no need to force a particular directory for the temp file
    Path tmp = Files.createTempFile("File_", ".tmp");
    // use import static java.nio.file.StandardOpenOption.*;
    // try( ... ) closes automatically, perfect for a temp file with DELETE_ON_CLOSE
    try(FileChannel tmpCh = FileChannel.open(tmp, READ, WRITE, DELETE_ON_CLOSE)) {
        // closing the target channel would also close rafTarget RandomAccessFile
        FileChannel target = rafTarget.getChannel();
        // just keep the data before start position, only copy remainder
        long retainStart = start + (long)quantity, toCopy = target.size() - retainStart;
        target.transferTo(retainStart, toCopy, tmpCh);
        // write the replacement
        target.write(ByteBuffer.wrap(replacers), start);
        // copy back the remainder, to the new position
        tmpCh.position(0);
        target.transferFrom(tmpCh, start + (long)replacers.length, toCopy);
        // adapt the length if necessary
        target.truncate(start + toCopy + replacers.length);
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58686657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档