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