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

我在Java中有此方法,并且我想对其进行改进。 该方法用于用新字节替换某些文件的某些部分(在开头,中间或结尾)(所选部分可以用更少或更多的字节替换)。 通过位置(start)和quantity完成选择。

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

这是我的旧代码:

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中的一些最佳替代方法(首选)。

现在测试如何?

  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,(int) raf.length()));
      String toBeChanged = "Latin America";
      String toBeInserted = "Colombia";
      int position = replacedContent.indexOf(toBeChanged);
      replaceBytesFile(raf,toBeChanged.length());
    } catch (IOException e) {
      System.out.println("Exception caught " + e.toString());
    }
  }

放置字节的方法!

  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());
    }
  }

方法获取文件!

  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

的内容
I want to travel to my Country.

TravelingToBeChanged.txt

的内容
I want to travel to India,Australia.

最后, TravelingToBeChanged.txt

的内容
I want to travel to India,Colombia,Australia.

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

您知道一些替代文件内容的替代方法吗?

zhejun4767 回答:在Java 8中优化某些文件的替换字节

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

例如代替

//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;
  }
}

只需使用

File temporalFile = File.createTempFile("File_",".tmp",userDirectory);

请参见createTempFile

进一步,而不是

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;
}

使用

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,总而言之,事情要简单得多

// 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);
    }
}
本文链接:https://www.f2er.com/3169307.html

大家都在问