我正在用Java编写一个程序,要求我比较2个文件中的数据。我必须检查文件1中的每一行与文件2的每一行,如果我找到匹配,则将它们写入第三个文件。在我读到文件2的末尾之后,如何将指针重置为文件的开头?
public class FiFo {
public static void main(String[] args)
{
FileReader file1=new FileReader("d:\\testfiles\\FILE1.txt");
FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt");
try{
String s1,s2;
while((s1=file1.data.readLine())!=null){
System.out.println("s1: "+s1);
while((s2=file2.data.readLine())!=null){
System.out.println("s2: "+s2);
}
}
file1.closeFile();
file2.closeFile();
}catch (IOException e) {
e.printStackTrace();
}
}
}
class FileReader {
BufferedReader data;
DataInputStream in;
public FileReader(String fileName)
{
try{
FileInputStream fstream = new FileInputStream(fileName);
data = new BufferedReader(new InputStreamReader(fstream));
}
catch (IOException e) {
e.printStackTrace();
}
}
public void closeFile()
{
try{
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:13)
我相信RandomAccessFile
就是你所需要的。它包含:RandomAccessFile#seek
和RandomAccessFile#getFilePointer
。
rewind()
是seek(0)
答案 1 :(得分:5)
我认为最好的办法是将文件1中的每一行放入HashMap
;那么你可以检查文件2的每一行是否为HashMap
的成员资格而不是为每行文件1读取整个文件一次。
但要回答关于如何返回文件开头的问题,最简单的方法是打开另一个InputStream
/ Reader
。
答案 2 :(得分:2)
显然你可以关闭并重新打开这样的文件:
while((s1=file1.data.readLine())!=null){
System.out.println("s1: "+s1);
FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt");
while((s2=file2.data.readLine())!=null){
System.out.println("s2: "+s2);
//compare s1 and s2;
}
file2.closeFile()
}
但你真的不想这样做,因为这个算法的运行时间是O(n 2 )。如果文件A中有1000行,文件B中有10000行,则内部循环将运行1,000,000次。
您应该做的是读取每一行并将其存储在一个集合中,该集合允许快速检查项目是否已经包含(可能是HashSet)。
如果您只需要检查文件2中的每一行是否在文件1中,那么您只需将文件1中的每一行添加到HashSet中,然后检查文件2中的每一行是否都在该集合中。
如果你需要进行交叉比较,你发现每个字符串都在一个而不是另一个,那么你需要两个哈希集,每个文件一个。 (虽然你可以做一个技巧只使用一个)
如果文件太大而你没有足够的内存,那么原来的n 2 方法无论如何都不会有效。
答案 3 :(得分:1)
好吧,Gennady S.回答是我用来解决你的问题的方法。
我正在用Java编写一个程序,要求我比较2个文件中的数据
然而,我宁愿不再对此进行编码..我宁愿使用像http://code.google.com/p/java-diff-utils/
这样的东西答案 4 :(得分:0)
正如其他人所建议的那样,您应该考虑解决问题的其他方法。对于返回文件中上一个点的具体问题,java.io.FileReader
会继承mark()
和reset()
方法来解决此问题。
答案 5 :(得分:0)
如上所述,有更好的算法 - 调查这些
除了:
FileReader没有实现标记和重置,因此trashgod的注释不准确。 您要么必须实现此版本(使用RandomAccessFile或不使用)或包装在BufferedReader中。但是,如果你标记它,后者会将整个内容加载到内存中
答案 6 :(得分:0)
只是一个简短的问题。你不能让一个对象指向文件的开头并用另一个对象遍历文件吗?然后,当你到达结束时,只需将其指向文件开头的对象(流)。我相信C ++有这样的文件I / O机制(或者它是流I / O)
答案 7 :(得分:0)
我相信您可以重新初始化文件2文件阅读器,并且应该重置它。
答案 8 :(得分:0)
如果您可以清楚地识别文件的维度,则可以使用 mark(int readAheadLimit)和 reset()从类< EM>的BufferedReader 。 方法 mark(int readAhedLimit)将标记添加到BufferedReader的当前位置,您可以使用 reset()返回标记。
使用它们你必须小心到 reset()之前要读取的字符数,你必须将它们指定为函数 mark(int readAhedLimit)。
假设您的代码应限制为100个字符:
class MyFileReader {
BufferedReader data;
int maxNumberOfCharacters = 100;
public MyFileReader(String fileName)
{
try{
FileInputStream fstream = new FileInputStream(fileName);
data = new BufferedReader(new InputStreamReader(fstream));
//mark the current position, in this case the beginning of the file
data.mark(maxNumberOfCharacters);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void resetFile(){
data.reset();
}
public void closeFile()
{
try{
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
答案 9 :(得分:0)
如果您只想将文件指针重置为文件顶部,请重新初始化缓冲区阅读器。我假设您还使用try和catch块来检查文件的结尾。
`//To read from a file.
BufferedReader read_data_file = new BufferedReader(new FileReader("Datafile.dat"));'
让我们说这就是你如何定义缓冲读卡器。现在,这是你可以检查file = null的结尾。
boolean has_data= true;
while(has_data)
{
try
{
record = read_data_file.readLine();
delimit = new StringTokenizer(record, ",");
//Reading the input in STRING format.
cus_ID = delimit.nextToken();
cus_name = delimit.nextToken();'
//And keep grabbing the data and save it in appropriate fields.
}
catch (NullPointerException e)
{
System.out.println("\nEnd of Data File... Total "+ num_of_records
+ " records were printed. \n \n");
has_data = false; //To exit the loop.
/*
------> This point is the trouble maker. Your file pointer is pointing at the end of the line.
-->If you want to again read all the data FROM THE TOP WITHOUT RECOMPILING:
Do this--> Reset the buffer reader to the top of the file.
*/
read_data_file = new BufferedReader(new FileReader(new File("datafile.dat")));
}
通过重新初始化缓冲区读取器,您将文件读取器标记/指针重置为文件顶部,您不必重新编译文件以将文件读取器标记/指针设置为文件的开头/顶部。 只有在您不想在同一次运行中重新编译和拉出相同的特技时,才需要重新初始化缓冲读取器。但是如果您希望只运行一次循环,那么您不必完成所有这些操作,只需重新编译文件,文件阅读器标记就会设置为文件的顶部/开头。