在Java中修改.txt文件

在Java中修改.txt文件,java,Java,我有一个文本文件,我想用Java编辑它。它有数千行。我基本上希望遍历这些行并更改/编辑/删除一些文本。这需要经常发生 从我在其他网站上看到的解决方案来看,一般的方法似乎是: 使用BufferedReader打开现有文件 阅读每一行,对每一行进行修改,并将其添加到StringBuilder 读取和修改所有文本后,将StringBuilder的内容写入新文件 用新文件替换旧文件 这个解决方案对我来说似乎有点“黑客”,特别是当我的文本文件中有数千行时 有谁知道更好的解决方案吗?我最近没有在Java

我有一个文本文件,我想用Java编辑它。它有数千行。我基本上希望遍历这些行并更改/编辑/删除一些文本。这需要经常发生

从我在其他网站上看到的解决方案来看,一般的方法似乎是:

  • 使用BufferedReader打开现有文件
  • 阅读每一行,对每一行进行修改,并将其添加到StringBuilder
  • 读取和修改所有文本后,将StringBuilder的内容写入新文件
  • 用新文件替换旧文件
这个解决方案对我来说似乎有点“黑客”,特别是当我的文本文件中有数千行时


有谁知道更好的解决方案吗?

我最近没有在Java中这样做,但将整个文件写入内存似乎是个坏主意

我能想到的最好办法是同时以写入模式打开一个临时文件,并对每一行进行读取,必要时进行修改,然后写入临时文件。最后,删除原始文件并重命名临时文件


如果您对文件系统具有修改权限,则可能还具有删除和重命名权限。

如果文件较大,您可能希望使用FileStream进行输出,但这似乎是执行您要求的操作的最简单过程(如果没有更详细的说明,即您尝试进行哪些类型的更改/编辑/删除,则无法确定哪种更复杂的方法可能有效).

通常情况下,您无法在位编辑文件;这只是一个非常长的字符序列,碰巧包含换行符。如果您的更改不改变每行中的字符数,您可以在位编辑。

没有理由缓冲整个文件

只需在阅读时写下每一行,必要时插入行,必要时删除行,必要时替换行


从根本上说,您不必大量重新创建文件,尤其是如果它只是一个文本文件。

它是什么类型的数据?您控制文件的格式吗

如果文件包含名称/值对(或类似的),您可能会有一些运气,或者可能会使用平面文件JDBC驱动程序拼凑一些东西


或者,您是否考虑过不经常写入数据?对文件的内存副本进行操作应该相对简单。如果没有需要实时更新文件的外部资源,则无需每次修改时都转到磁盘。您可以运行计划任务来定期写入如果您担心数据备份,请更新磁盘。

如果文件只有几千行,您应该能够在一次读取中读取整个文件并将其转换为字符串

您可以使用ApacheIOutils,其方法如下所示

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) {
    }
}

如果你知道你想要改变什么,你就不能使用正则表达式吗?也许应该这样做。

我认为,
FileOutputStream.getFileChannel()
会有很大帮助,请参阅FileChannel api

虽然这个问题是很久以前发布的,但我认为最好把我的答案放在这里。 我认为在这种情况下,最好的方法是使用
java.nio.channels
包中的
FileChannel
但是,只有当您需要具有良好的性能时,才需要使用
RandomAccessFile
获得
FileChannel
,如下所示:

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

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

}
在此之后,您需要创建一个
ByteBuffer
,从
FileChannel
读取

这看起来像这样:

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

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

}

java.nio.ByteBuffer inBuffer=java.nio.ByteBuffer.allocate(100);
int pos=0;
int aux=0;
StringBuilder sb=新的StringBuilder();
而(位置!=-1){
aux=通道读取(缓冲区内,位置);
位置=(辅助!=-1)?位置+辅助:-1;
b=inBuffer.array();
sb.删除(0,sb.length());
对于(int i=0;i

希望我的回答能对您有所帮助!

您可以使用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();
}
public类RandomAccessFileUtil{
公共静态最终长记录长度=100;
公共静态最终字符串为空_String=“”;
公共静态最终字符串CRLF=“\n”;
公共静态最终字符串PATHNAME=“/home/mjiang/JM/mahtew.txt”;
/**
*一二三
要附加的文本
567
8910
* 
* 
*@param args
*@抛出异常
*/
公共静态void main(字符串[]args)引发IOException
{
String starPrefix=“要附加的文本”;
String replacedString=“已追加新文本”;
RandomAccessFile文件=新的RandomAccessFile(新文件(路径名),“rw”);
字符串行=”;
而((line=file.readLine())!=null)
{
if(行起始带(起始前缀))
{
seek(file.getFilePointer()-RECORD_LENGTH-1);
file.writeBytes(replacedString);
}
}
}
公共静态void createFile()引发IOException
{
RandomAccessFile文件=新的RandomAccessFile(新文件(路径名),“rw”);
字符串line1=“一二三”;
String line2=“要附加的文本”;
字符串line3=“五六七”;
字符串line4=“八九十”;
file.writeBytes(paddingRight(第1行));
文件写入字节(CRLF);
file.writeBytes(paddingRight(第2行));