我有一个250 GB的大.txt文件,我的硬盘上只有50 GB的空间。 此.txt文件中的每一行都有一个长前缀,我想删除此前缀 使该文件更小。
首先,我想逐行阅读,更改并将其写入另一个文件。
// read line out of first file
line = line.replace(prefix, "");
// write line into second file
问题是我没有足够的空间。
那么如何从文件中删除所有前缀呢?
答案 0 :(得分:8)
检查RandomAccessFile:http://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html
您必须跟踪您正在阅读的位置以及您要写入的位置。最初两者都在开始。然后你读N个字节(一行),缩短它,寻找N个字节并写M个字节(缩短的行)。然后你寻找前向(N - M)字节,回到下一行开始的位置。然后你一遍又一遍地这样做。最后用setLength(long)截断多余的部分。
您也可以批量进行(例如阅读4kb,处理,写入,重复)以提高效率。
所有语言的流程都相同。有些人通过在API后面隐藏搜索来更容易。
当然,您必须绝对确保您的程序完美无缺,因为无法撤消此过程。
此外,RandomAccessFile有点受限,因为它无法告诉您文件在给定时刻的位置。因此,您必须在“解码字符串”和“编码字节”之间进行转换。如果您的文件是UTF-8,则字符串中的给定字符可以占用文件中的一个字节。所以你不能只做seek(string.length())。您必须使用seek(string.getBytes(encoding).length)并考虑可能的换行符转换(Windows使用两个字符进行换行,Unix只使用一个)。但是如果你有ASCII,ISO-Latin-1或类似的普通字符编码并且知道文件有什么换行符,那么问题应该很简单。
当我编辑我的答案以匹配所有可能的极端情况时,我认为最好使用BufferedReader读取文件并更正字符编码,并打开RandomAccessFile进行写入。如果您的操作系统支持将文件打开两次。这样您就可以从BufferedReader获得完整的Unicode支持,并且您不必跟踪读取和写入位置。您必须使用RandomAccessFile进行写入,因为对文件使用Writer可能只是截断它(尽管没有尝试过)。
像这样的东西。它适用于琐碎的例子,但它没有错误检查,我绝对不保证。首先在较小的文件上测试它。
public static void main(String[] args) throws IOException {
File f = new File(args[0]);
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(f), "UTF-8")); // Use correct encoding here.
RandomAccessFile writer = new RandomAccessFile(f, "rw");
String line = null;
long totalWritten = 0;
while ((line = reader.readLine()) != null) {
line = line.trim() + "\n"; // Remove your prefix here.
byte[] b = line.getBytes("UTF-8");
writer.write(b);
totalWritten += b.length;
}
reader.close();
writer.setLength(totalWritten);
writer.close();
}
答案 1 :(得分:0)
您可以使用 RandomAccessFile 。这允许您覆盖文件的一部分。由于javadoc中没有提到复制或缓存机制,因此无需额外的磁盘空间即可使用。
所以你可以用空格覆盖不需要的部分。
答案 2 :(得分:-1)
从it does not have to be done in Java开始,我会推荐Python:
将replace.py中的以下内容保存在与文本文件相同的文件夹中:
import fileinput
for line in fileinput.input("your-file.txt", inplace=True):
print "%s" % (line.replace("oldstring", "newstring"))
用字符串替换两个字符串并执行python replace.py