Чтение файла и добавление текста в случайное расположение символов

У меня есть текстовый файл с последовательностью 4194304 букв, начиная от AD все в одну строку (4 МБ). Как бы я случайно указал на символ и заменил следующий набор символов на другой файл длиной 100 символов и записал его в файл? В настоящее время я действительно могу сделать это, но я чувствую, что это действительно неэффективно, когда я повторяю это несколько раз.

Вот иллюстрация того, что я упомянул выше: Ссылка на Imageshack

Вот как я сейчас достигаю этого:

Random rnum = new Random();
FileInputStream fin = null;
FileOutputStream fout = null;
int count = 10000;
FileInputStream fin1 = null;

File file1 = new File("fileWithSet100C.txt");

int randChar = 0;
while(cnt > 0){
    try {
        int c = 4194304 - 100;

        randChar = rnum.nextInt(c);
        File file = new File("file.txt");

                    //seems inefficient to initiate these guys over and over 
        fin = new FileInputStream(file);
        fin1 = new FileInputStream(file1);

        //would like to remove this and have it just replace the original
        fout = new FileOutputStream("newfile.txt");

        int byte_read;
        int byte_read2;

        byte[] buffer = new byte[randChar]; 
        byte[] buffer2 = new byte[(int)file1.length()]; //4m

        byte_read = fin.read(buffer);
        byte_read2 = fin1.read(buffer2);

        fout.write(buffer, 0, byte_read);
        fout.write(buffer2, 0, byte_read2);

        byte_read = fin.read(buffer2);
        buffer = new byte[4096]; //4m
        while((byte_read = (fin.read(buffer))) != -1){
            fout.write(buffer, 0, byte_read);
        }

        cnt--;
    }
    catch (...) {
        ...
    }
    finally {
          ...
    }
    try{
        File file = new File("newfile.txt");
        fin = new FileInputStream(file);
        fout = new FileOutputStream("file.txt");
        int byte_read;
        byte[] buffer = new byte[4096]; //4m
        byte_read = fin.read(buffer);
    while((byte_read = (fin.read(buffer))) != -1){
        fout.write(buffer, 0, byte_read);
    }
    }
    catch (...) {
        ...
    }
    finally {
          ...
    }

Спасибо за прочтение!

РЕДАКТИРОВАТЬ: Для тех, кому интересно, вот код, который я использовал для решения вышеупомянутой проблемы:

String stringToInsert = "insertSTringHERE";
byte[] answerByteArray = stringToInsert.getBytes();
ByteBuffer byteBuffer = ByteBuffer.wrap(answerByteArray);
Random rnum = new Random();
randChar = rnum.nextInt(4194002); //4MB worth of bytes

File fi = new File("file.txt");

RandomAccessFile raf = null;
try {
    raf = new RandomAccessFile(fi, "rw");
} catch (FileNotFoundException e1) {
    // TODO error handling and logging
}

FileChannel fo = null;
fo = raf.getChannel();

// Move to the beginning of the file and write out the contents
// of the byteBuffer.
try {
    outputFileChannel.position(randChar);
    while(byteBuffer.hasRemaining()) {
        fo.write(byteBuffer);
}
} catch (IOException e) {
    // TODO error handling and logging
}
try {
    outputFileChannel.close();
} catch (IOException e) {
    // TODO error handling and logging
}
try {
    randomAccessFile.close();
} catch (IOException e) {
    // TODO error handling and logging
}

2 ответа

Решение

Вы, вероятно, хотите использовать функции файлов с произвольным доступом в Java. У Sun/Oracle есть учебник по файлам произвольного доступа, который, вероятно, будет вам полезен.

Если вы не можете использовать Java 7, посмотрите на Random Access File, который также имеет функцию поиска и существует с Java 1.0.

Во-первых, для ваших файлов вы можете использовать файлы в качестве глобальных переменных. Это все, что вам нужно использовать файл, когда вам нужно, не читая его снова. Также обратите внимание, что если вы продолжите создавать новые файлы, вы потеряете уже полученные данные.

Например:

public class Foo {

  // Gloabal Vars //
  File file;

  public Foo(String location) {
     // Do Something
    file = new File(location);
  }

  public add() {
    // Add
  }

}

Отвечая на ваш вопрос, я сначала прочитал бы оба файла, а затем сделал все необходимые изменения в памяти. После того, как вы внесли все изменения, я запишу эти изменения в файл.

Однако, если файлы очень большие, я бы внес все изменения по одному на диске... это будет медленнее, но при этом вам не хватит памяти. Для того, что вы делаете, я сомневаюсь, что вы могли бы использовать буфер, чтобы помочь противостоять тому, насколько медленным это будет.

Мое общее предложение было бы использовать массивы. Например, я бы сделал следующее...

public char[] addCharsToString(String str, char[] newChars, int index) {
        char[] string = str.toCharArray();
        char[] tmp = new char[string.length + newChars.length];
        System.arraycopy(string, 0, tmp, 0, index);
        System.arraycopy(newChars, index, tmp, index, newChars.length);
        System.arraycopy(string, index + newChars.length, tmp, index + newChars.length, tmp.length - (newChars.length + index));
        return tmp;
}

Надеюсь это поможет!

Другие вопросы по тегам