Как я могу Reset Указатель файла к началу файла в Java?

Я пишу программу на Java, которая требует, чтобы я сравнивал данные в 2 файлах. Я должен проверить каждую строку из файла 1 на каждую строку файла 2, и если я найду совпадение, напишите их в третий файл. После того, как я прочитал в конце файла 2, как я reset указатель на начало файла?

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();
        }
    }
}

Ответ 1

Я считаю, RandomAccessFile - это то, что вам нужно. Он содержит: RandomAccessFile#seek и RandomAccessFile#getFilePointer.

rewind() - seek(0)

Ответ 2

Думаю, лучше всего поставить каждую строку из файла 1 в HashMap; то вы можете проверить каждую строку файла 2 для членства в HashMap, а не читать весь файл один раз для каждой строки файла 1.

Но чтобы ответить на вопрос о том, как вернуться к началу файла, проще всего открыть еще один InputStream/Reader.

Ответ 3

Очевидно, вы могли бы просто закрыть и снова открыть файл следующим образом:

     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, вы просто добавляете каждую строку в файл один в HashSet, а затем проверяете, чтобы каждая строка в файле 2 находилась в этом наборе,

Если вам нужно выполнить перекрестное сравнение, где вы найдете каждую строку, которая находится в одном, а не другом, тогда вам понадобятся два набора хэшей, по одному для каждого файла. (Хотя есть трюк, который вы можете сделать, чтобы использовать только один)

Если файлы настолько велики, что у вас недостаточно памяти, тогда ваш оригинальный метод n 2 никогда бы не сработал.

Ответ 4

Хорошо, ответ Геннадия С. - то, что я буду использовать для решения вашей проблемы.

Я пишу программу на Java, которая требует, чтобы я сравнивал данные в 2 файлах

однако я бы предпочел не кодировать это снова. Я бы предпочел использовать что-то вроде http://code.google.com/p/java-diff-utils/

Ответ 5

Как и другие, вы должны рассмотреть другие подходы к проблеме. Для конкретного вопроса о возврате к предыдущему пункту в файле java.io.FileReader наследует mark() и reset() методы, направленные на достижение этой цели.

Ответ 6

Как уже отмечалось, существуют лучшие алгоритмы - исследуйте эти

в стороне:

FileReader не реализует метки и reset, поэтому комментарии trashgod неточны. Вам нужно либо реализовать версию этого (с использованием RandomAccessFile, либо нет), либо обернуть в BufferedReader. Тем не менее, последний будет загружать все это в память, если вы отметите его

Ответ 7

Просто быстрый вопрос. не можете ли вы сохранить один объект, указанный в начале файла, и пройти через файл с другим объектом? Затем, когда вы дойдете до конца, просто укажите его на объект в начале файла (потока). Я считаю, что С++ имеет такие механизмы с файловым вводом-выводом (или это потоковый ввод-вывод)

Ответ 8

Я считаю, что вы можете просто повторно инициализировать файловый читатель файла 2, и он должен reset его.

Ответ 9

Если вы можете четко указать размер вашего файла, вы можете использовать mark (int readAheadLimit) и reset() из класса BufferedReader. Метка метода (int readAhedLimit) добавляет маркер в текущую позицию вашего BufferedReader, и вы можете вернуться к маркеру с помощью reset().

Используя их, вы должны быть осторожными до количества символов, которые нужно читать до reset(), вы должны указать их как аргумент метки функции (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();
        }
    }
}

Ответ 10

Если вы просто хотите, чтобы reset указатель файла в верхней части файла, повторите инициализацию вашего буферизатора. Я предполагаю, что вы также используете блок try и catch для проверки конца файла.

`//To read from a file. 
      BufferedReader read_data_file = new BufferedReader(new FileReader("Datafile.dat"));'

Скажем так, как вы определили свой буферный читатель. Итак, вот как вы можете проверить конец файла = 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")));
}

Повторно инициализируя буферизатор, вы будете reset указатель файла/указатель на верхнюю часть файла, и вам не придется перекомпилировать файл, чтобы установить маркер/указатель файла для начала/вершины файла, Вам нужно повторно инициализировать буферизатор, только если вы не хотите перекомпилировать и снять один и тот же трюк в одном и том же режиме. Но если вы хотите просто запустить цикл один раз, то вам не нужно все это, просто перекомпилировав файл, маркер чтения файла будет установлен в начало/начало файла.