在Java中修改.txt文件
我有一个我想用Java编辑的文本文件。 它有成千上万的线。 我基本上想遍历行和更改/编辑/删除一些文本。 这将需要经常发生。
从我在其他网站上看到的解决scheme来看,一般的做法似乎是:
- 使用BufferedReader打开现有的文件
- 阅读每一行,对每行进行修改,并将其添加到StringBuilder
- 一旦所有的文本被读取和修改,写入StringBuilder的内容到一个新的文件
- 用新文件replace旧文件
这个解决scheme对我来说似乎有点“黑客”,特别是如果我在我的文本文件中有成千上万行。
任何人都知道更好的解决scheme?
我最近在Java中没有这样做,但是将整个文件写入内存似乎是一个坏主意。
我能想到的最好的办法是同时打开一个临时文件写入模式,并对每一行读取,必要时修改,然后写入临时文件。 最后,删除原始文件并重命名临时文件。
如果您在文件系统上拥有修改权限,则可能还需要删除和重命名权限。
如果文件只有几千行,你应该可以在一次读取中读取整个文件并将其转换为string。
你可以使用具有如下方法的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) { } }
如果文件很大,可能需要使用FileStream进行输出,但是看起来好像是最简单的一个stream程就可以完成所要求的操作(并且没有更多的特殊性,例如,你需要什么types的修改/编辑/删除试图去做,不可能确定更复杂的方式可能工作)。
没有理由缓冲整个文件。
简单地写每行读取它,必要时插入行,必要时删除行,必要时更换行。
从根本上说,你不会得到重新创build批量文件,特别是如果它只是一个文本文件。
它是什么样的数据? 你是否控制文件的格式?
如果文件包含名称/值对(或类似),则可以使用Properties ,或者使用平面文件JDBC驱动程序将某些东西拼凑在一起。
或者,你有没有考虑过不经常写这些数据? 在文件的内存拷贝上操作应该是相对简单的。 如果没有需要实时更新文件的外部资源,则每次需要修改时都不需要到磁盘。 如果您担心数据备份,您可以运行计划任务以定期将更新写入磁盘。
一般来说,你不能编辑文件; 它只是一个非常长的字符序列,恰好包含换行符。 如果您的更改不会更改每行中的字符数,则可以进行编辑。
如果你知道你想改变什么,你不能使用正则expression式吗? 雅加达Regexp应该可以做的伎俩。
虽然这个问题是前一段时间发布的,但我觉得把这个答案放在这里是很好的。 我认为最好的方法是在这种情况下使用来自java.nio.channels
包的FileChannel
。 但是,这只有当你需要有一个良好的performance! 你需要通过一个RandomAccessFile
获得一个FileChannel
,像这样:
java.nio.channels.FileChannel channel = new java.io.RandomAccessFile("/my/fyle/path", "rw").getChannel();
在此之后,您需要创build一个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); }
希望我的回答能帮助你!
我认为, FileOutputStream.getFileChannel()
将帮助很多,请参阅FileChannel api http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html
您可以在Java中使用RandomAccessFile来修改文件:每行的大小必须是固定的,否则当写入新string时,可能会覆盖下一行中的string。
因此,在我的例子中,当创build文件并写回文件时,我将行长度设置为100,并用空格string填充。
所以为了允许更新,你需要设置行的长度比这个文件中行的最长长度稍大。
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(); }
}
通过点击“Save As”并保存* .java扩展名,可以将txt文件更改为java。