我有一个我想用Java编辑的文本文件。它有成千上万行。我基本上想要遍历这些行并更改/编辑/删除一些文本。这需要经常发生。
从我在其他网站上看到的解决方案来看,一般方法似乎是:
这个解决方案对我来说似乎有点“hacky”,特别是如果我的文本文件中有数千行。
有人知道更好的解决方案吗?
答案 0 :(得分:30)
我最近没有用Java做过这个,但是将整个文件写入内存似乎是一个坏主意。
我能想到的最好的想法是同时在写入模式下打开一个临时文件,对于每一行,读取它,必要时进行修改,然后写入临时文件。最后,删除原始文件并重命名临时文件。
如果您对文件系统具有修改权限,则可能还具有删除和重命名权限。
答案 1 :(得分:5)
如果文件只有几千行,你应该能够在一次读取中读取整个文件并将其转换为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) {
}
}
答案 2 :(得分:2)
如果文件很大,你可能想要使用FileStream进行输出,但这看起来非常像是你所要求的最简单的过程(没有更多的特殊性,即什么类型的更改/编辑) /你想要做的删除,不可能确定哪种更复杂的方法可行。)
答案 3 :(得分:2)
没有理由缓冲整个文件。
只需在阅读时写下每一行,必要时插入行,必要时删除行,必要时替换行。
从根本上说,你不需要重新创建批发文件,特别是如果它只是一个文本文件。
答案 4 :(得分:2)
它是什么类型的数据?你控制文件的格式吗?
如果文件包含名称/值对(或类似对象),您可以运气Properties,或者使用平面文件JDBC驱动程序拼凑一些东西。
或者,您是否考虑过不经常写数据?在文件的内存中复制操作应该相对简单。如果没有需要实时更新文件的外部资源,则每次要进行修改时都不需要转到磁盘。如果您担心数据备份,可以运行计划任务以定期更新磁盘。
答案 5 :(得分:1)
通常,您无法在适当的位置编辑文件;它只是一个很长的字符序列,恰好包含换行符。如果您的更改未更改每行中的字符数,则可以就地编辑。
答案 6 :(得分:1)
如果您知道要更改的内容,是否可以使用正则表达式? Jakarta Regexp应该可以做到这一点。
答案 7 :(得分:1)
我认为,FileOutputStream.getFileChannel()
会有很多帮助,请参阅FileChannel api
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html
答案 8 :(得分:1)
虽然这个问题是在很久以前发布的,但我觉得把答案放在这里是件好事。
我认为最好的方法是在此方案中使用FileChannel
包中的java.nio.channels
。 但是,这只有你需要有一个好的表现!你需要通过FileChannel
获得RandomAccessFile
,如下所示:
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);
}
希望我的回答能帮到你!
答案 9 :(得分: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();
}
}
答案 10 :(得分:-2)
您可以通过点击&#34;另存为&#34;将txt文件更改为java。并保存* .java扩展名。