2009-05-04 64 views
26

我有一個我想用Java編輯的文本文件。它有數千行。我基本上想要遍歷行並更改/編輯/刪除一些文本。這將需要經常發生。修改Java中的.txt文件

從我在其他網站上看到了解決方案,一般的方法似乎是:使用

  • 打開現有的文件一個BufferedReader
  • 閱讀每一行,進行修改,每一行,並將其添加到一個StringBuilder
  • 一旦所有的文字已被讀取和修改,寫的StringBuilder的內容到一個新的文件
  • 與新文件
取代舊文件

這個解決方案對我來說似乎有點「黑客」,特別是當我在我的文本文件中有數千行時。

有人知道更好的解決方案嗎?

+0

您可以使用Java中的RandomAccessFile修改文件,而無需回寫整個文件。查看我發佈的以下詳細信息。 – sendon1982 2014-03-28 02:40:42

回答

29

我沒有在Java中做到了這一點最近,但寫整個文件到內存似乎是一個壞主意。

,我能想出的最好的辦法是開在同一時間以書面方式臨時文件,併爲每一行,讀它,需要進行修改,然後寫入到臨時文件。最後,刪除原始文件並重命名臨時文件。

如果您有修改文件系統的權限,也可能有刪除和重命名的權限。

+1

原來我的回答錯了;我忘記了RandomAccessFile不允許插入或刪除。我認爲這是最好的答案。 – 2009-05-04 21:40:50

2

如果文件較大,則可能需要使用輸出一個FileStream,但似乎很像是做什麼你問的簡單過程(且不即在什麼類型的變化更特異性/您試圖執行的編輯/刪除操作,無法確定更復雜的工作方式)。

1

一般而言,您不能編輯文件;它只是一個非常長的字符序列,恰好包含換行符。如果您的更改不會更改每行中的字符數,則可以進行編輯。

2

無理由緩衝整個文件。

簡單地寫每一行作爲你讀它,插入線在必要時,刪除線在必要的時候,必要時更換線路。

從根本上說,你不會得到周圍不必重新創建該文件的批發,特別是如果它只是一個文本文件。

2

它是什麼樣的數據?你是否控制文件的格式?

如果文件包含名稱/值對(或類似對象),則可以使用Properties或使用平面文件JDBC驅動程序將一些東西拼湊在一起。

或者,您是否考慮過不經常寫數據?在文件的內存拷貝上操作應該是相對簡單的。如果沒有需要實時更新文件的外部資源,則每次需要進行修改時都不需要轉到磁盤。如果您擔心數據備份,您可以運行計劃任務以定期將更新寫入磁盤。

5

如果文件只有幾千行,您應該能夠在一次讀取中讀取整個文件並將其轉換爲字符串。

您可以使用具有如下方法的apache IOUtils。

public static String readFile(String filename) throws IOException { 
    File file = new File(filename); 
    int len = (int) file.length(); 
    byte[] bytes = new byte[len]; 
    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(file); 
     assert len == fis.read(bytes); 
    } catch (IOException e) { 
     close(fis); 
     throw e; 
    } 
    return new String(bytes, "UTF-8"); 
} 

public static void writeFile(String filename, String text) throws IOException { 
    FileOutputStream fos = null; 
    try { 
     fos = new FileOutputStream(filename); 
     fos.write(text.getBytes("UTF-8")); 
    } catch (IOException e) { 
     close(fos); 
     throw e; 
    } 
} 

public static void close(Closeable closeable) { 
    try { 
     closeable.close(); 
    } catch(IOException ignored) { 
    } 
} 
1

如果您知道要更改什麼,不能使用正則表達式嗎? Jakarta Regexp應該可以做到這一點。

1

雖然這個問題是前一段時間發佈的,我覺得這是好事,這裏把我的答案。 我認爲最好的方法是在這種情況下使用java.nio.channels包中的FileChannel但是,只有當你需要有一個良好的表現!您需要通過RandomAccessFile獲得FileChannel,像這樣:

java.nio.channels.FileChannel channel = new java.io.RandomAccessFile("/my/fyle/path", "rw").getChannel();

在此之後,你需要創建一個ByteBuffer在那裏你會從FileChannel讀取。

這看起來是這樣的:


java.nio.ByteBuffer inBuffer = java.nio.ByteBuffer.allocate(100); 
int pos = 0; 
int aux = 0; 
StringBuilder sb = new StringBuilder(); 

while (pos != -1) { 

    aux = channel.read(inBuffer, pos); 
    pos = (aux != -1) ? pos + aux : -1; 

    b = inBuffer.array(); 
    sb.delete(0, sb.length()); 

    for (int i = 0; i < b.length; ++i) { 

     sb.append((char)b[i]); 

    } 

    //here you can do your stuff on sb 

    inBuffer = ByteBuffer.allocate(100); 

} 

希望我的回答可以幫助你!

1

您可以使用Java中的RandomAccessFile在一種情況下修改文件: 否則每行的大小必須是固定的,當寫入新字符串時,它可能會覆蓋下一行中的字符串。

因此,在我的例子中,當創建文件並寫回文件時,我將行長設置爲100,並用空格字符串填充。

因此,爲了允許更新,您需要將行的長度設置爲比此文件中行的最長長度稍大。

public class RandomAccessFileUtil { 
public static final long RECORD_LENGTH = 100; 
public static final String EMPTY_STRING = " "; 
public static final String CRLF = "\n"; 

public static final String PATHNAME = "/home/mjiang/JM/mahtew.txt"; 

/** 
* one two three 
    Text to be appended with 
    five six seven 
    eight nine ten 
* 
* 
* @param args 
* @throws IOException 
*/ 
public static void main(String[] args) throws IOException 
{ 
    String starPrefix = "Text to be appended with"; 
    String replacedString = "new text has been appended"; 

    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw"); 

    String line = ""; 
    while((line = file.readLine()) != null) 
    { 
     if(line.startsWith(starPrefix)) 
     { 
      file.seek(file.getFilePointer() - RECORD_LENGTH - 1); 
      file.writeBytes(replacedString); 
     } 

    } 
} 

public static void createFile() throws IOException 
{ 
    RandomAccessFile file = new RandomAccessFile(new File(PATHNAME), "rw"); 

    String line1 = "one two three"; 
    String line2 = "Text to be appended with"; 
    String line3 = "five six seven"; 
    String line4 = "eight nine ten"; 

    file.writeBytes(paddingRight(line1)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line2)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line3)); 
    file.writeBytes(CRLF); 
    file.writeBytes(paddingRight(line4)); 
    file.writeBytes(CRLF); 

    file.close(); 

    System.out.println(String.format("File is created in [%s]", PATHNAME)); 
} 

public static String paddingRight(String source) 
{ 
    StringBuilder result = new StringBuilder(100); 
    if(source != null) 
    { 
     result.append(source); 
     for (int i = 0; i < RECORD_LENGTH - source.length(); i++) 
     { 
      result.append(EMPTY_STRING); 
     } 
    } 

    return result.toString(); 
} 

}

0

可以通過保存上單擊 「另存爲」 並保存* .java擴展名更改txt文件到Java。