13

I need to write something into a text file's beginning. I have a text file with content and i want write something before this content. Say i have;

Good afternoon sir,how are you today?
I'm fine,how are you?
Thanks for asking,I'm great

After modifying,I want it to be like this:

Page 1-Scene 59
25.05.2011

Good afternoon sir,how are you today?
I'm fine,how are you?
Thanks for asking,I'm great

Just made up the content :) How can i modify a text file like this way?

Athafoud
  • 2,898
  • 3
  • 40
  • 58
toruko
  • 275
  • 1
  • 4
  • 11
  • @Turuko The first thing you must identify is a delimiter. Without delimiters (whether explicit or implicit) you cannot achieve your goal. This is more easily understood by asking yourself this question, "How will I know when to insert the page and scene header above the dialog?" If you have no way to determine where you are in the text file then you can't do it. – Matthew Cox May 25 '11 at 16:27
  • 2
    @Matthew: I don't see the problem here - it's writing a fixed bit of text at the very start of the text file. There's no need to recognize anything, at least as far as the question has been asked. – Jon Skeet May 25 '11 at 16:30
  • @Jon Perhaps I misunderstood the question. I understood the question to be asking, "I have this text file, how can I modify it to add this metadata between certain sections throughout the file". – Matthew Cox May 25 '11 at 16:33
  • @Jon and @Turuko If you are just looking to insert this header information once at the beginning of the file then you can disregard my comment. =P – Matthew Cox May 25 '11 at 16:34
  • See also http://stackoverflow.com/questions/822150/modify-a-txt-file-in-java?lq=1 – Raedwald Mar 18 '14 at 16:28

6 Answers6

26

You can't really modify it that way - file systems don't generally let you insert data in arbitrary locations - but you can:

  • Create a new file
  • Write the prefix to it
  • Copy the data from the old file to the new file
  • Move the old file to a backup location
  • Move the new file to the old file's location
  • Optionally delete the old backup file
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This looks like something doable for my question. Thanks for answer. Really appreciated. I'll right get into it. – toruko May 25 '11 at 16:41
  • Is this process a huge waste of resources ? I am searching for a cost effective implementation. – Poutrathor Jul 03 '15 at 08:06
  • @Poutrathor: What exactly do you mean by "cost effective"? (That's only the same as "efficient" if there's a real cost to inefficiency.) Basically, if you want to be able to perform random insertions/deletions, you probably don't want to store it as a plain text file... – Jon Skeet Jul 03 '15 at 08:07
  • 1
    @JonSkeet English is not my forte, sry. I work on a hardware constraints device (the device is not that powerful). Thus I should try to implement solutions that ask the less work to the CPU and RAM load. File manipulation might be heavy especially if I have to copy. Context : I want to display my logs in inverse time : the last log first. I see only 2 ways : write the last log at the top of the file, read the file from bottom to top. I don't know which is best. Since it is an open question, I don't know either where to ask, so I am browsing SO answer in order to find by myself :) – Poutrathor Jul 03 '15 at 08:13
  • 1
    @Poutrathor: Well I'd definitely implement reading the file backwards in that case... possibly splitting the file into chunks (e.g. a new log file per hour) to make it simpler. – Jon Skeet Jul 03 '15 at 08:19
  • @JonSkeet Thanks for the advice ! It seems too to me that the insertion was costly. Unbelievable how bad file manipulation is in 2015 – Poutrathor Jul 03 '15 at 08:21
16

Just in case it will be useful for someone here is full source code of method to prepend lines to a file using Apache Commons IO library. The code does not read whole file into memory, so will work on files of any size.

public static void prependPrefix(File input, String prefix) throws IOException {
    LineIterator li = FileUtils.lineIterator(input);
    File tempFile = File.createTempFile("prependPrefix", ".tmp");
    BufferedWriter w = new BufferedWriter(new FileWriter(tempFile));
    try {
        w.write(prefix);
        while (li.hasNext()) {
            w.write(li.next());
            w.write("\n");
        }
    } finally {
        IOUtils.closeQuietly(w);
        LineIterator.closeQuietly(li);
    }
    FileUtils.deleteQuietly(input);
    FileUtils.moveFile(tempFile, input);
}
hgrey
  • 3,033
  • 17
  • 21
2

As @atk suggested, java.nio.channels.SeekableByteChannel is a good interface. But it is available from 1.7 only.

Update : If you have no issue using FileUtils then use

String fileString = FileUtils.readFileToString(file);
Tisho
  • 8,320
  • 6
  • 44
  • 52
Sumit Purohit
  • 168
  • 2
  • 12
2

I think what you want is random access. Check out the related java tutorial. However, I don't believe you can just insert data at an arbitrary point in the file; If I recall correctly, you'd only overwrite the data. If you wanted to insert, you'd have to have your code

  1. copy a block,
  2. overwrite with your new stuff,
  3. copy the next block,
  4. overwrite with the previously copied block,
  5. return to 3 until no more blocks
atk
  • 9,244
  • 3
  • 32
  • 32
  • 1
    Random access usually allows you to *overwrite* data at arbitrary points - not *insert* data within a file. – Jon Skeet May 25 '11 at 16:43
  • Jon, Yeah, I was in the middle of editing my response while you were commenting :) – atk May 25 '11 at 16:45
1

This isn't a direct answer to the question, but often files are accessed via InputStreams. If this is your use case, then you can chain input streams via SequenceInputStream to achieve the same result. E.g.

InputStream inputStream = new SequenceInputStream(new ByteArrayInputStream("my line\n".getBytes()), new FileInputStream(new File("myfile.txt")));
Max
  • 15,157
  • 17
  • 82
  • 127
0

I will leave it here just in case anyone need

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try (FileInputStream fileInputStream1 = new FileInputStream(fileName1);
         FileInputStream fileInputStream2 = new FileInputStream(fileName2)) {

        while (fileInputStream2.available() > 0) {
            byteArrayOutputStream.write(fileInputStream2.read());
        }
        while (fileInputStream1.available() > 0) {
            byteArrayOutputStream.write(fileInputStream1.read());
        }
    }
    try (FileOutputStream fileOutputStream = new FileOutputStream(fileName1)) {
        byteArrayOutputStream.writeTo(fileOutputStream);
    }
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 12 '22 at 19:44