Как я могу сбросить указатель файла на начало файла в Java? - PullRequest
12 голосов
/ 09 февраля 2010

Я пишу программу на 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();
        }
    }
}

Ответы [ 10 ]

13 голосов
/ 09 февраля 2010

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

rewind() - это seek(0)

5 голосов
/ 09 февраля 2010

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

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

2 голосов
/ 09 февраля 2010

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

     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 никогда бы не сработал.

1 голос
/ 09 февраля 2010

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

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

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

0 голосов
/ 28 июля 2016

Если вы просто хотите сбросить указатель файла на верхнюю часть файла, переинициализируйте буфер чтения. Я предполагаю, что вы также используете блок 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")));
}

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

0 голосов
/ 01 апреля 2016

Если вы можете четко определить размер вашего файла, вы можете использовать mark (int readAheadLimit) и reset () из класса 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();
        }
    }
}
0 голосов
/ 23 января 2014

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

0 голосов
/ 19 марта 2010

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

0 голосов
/ 19 марта 2010

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

в сторону:

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

0 голосов
/ 09 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...