Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > чтение из файла в обратном направлении


Автор: lihusha 14.6.2009, 11:10
Здравствуйте.

Подскажите , пожалуйста , как прочитать файл "file.txt" в обратном направлении, т.е. , начиная с конца файла к началу

Спасибо

Автор: ecologist 14.6.2009, 13:58
Смотри RandomAccessFile - перемещайся и читай побайтно.

Автор: lihusha 14.6.2009, 14:34
примерчика не найдется ?

Автор: lihusha 14.6.2009, 15:30
Разобрался

Вот примерчик

Код


package phoenix;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;


public class Reverse {

    private File file;
    RandomAccessFile raf;
    FileWriter fw;

    public Reverse(String fileName) throws FileNotFoundException, IOException {
        createFile(fileName);
        raf = new RandomAccessFile(file, "rw");
        fw = new FileWriter(file, true);

    }

    private void createFile(String fileName) throws IOException {
        this.file = new File(fileName);
        file.createNewFile();
    }

    public void reverseReadFromFile() throws FileNotFoundException, IOException {


        String line = "";
        int read = 0;


        long fileLength = file.length();

        for (int i = 0; i <= fileLength; i++) {
            raf.seek(fileLength - i);
            read = raf.read();
            line += (char) read;
        }
        System.out.println("Чтение из файла в обратном направлении");

        System.out.println(line + "\n\n");
    }

    public void readFromFile() throws IOException {


        String output = null;
        System.out.println("Чтение из файла в прямом направлении");
        while ((output = raf.readLine()) != null) {
            System.out.println(output);
        }
        System.out.println("\n\n");
    }

    public void writeToFile(String text) throws IOException {


        fw.write(text);
        fw.flush();
        fw.close();


        System.out.println("Текст '" + text + "' был записан в файл '" + file.getName() + "'\n\n");
    }

    public static void main(String args[]) throws FileNotFoundException, IOException {

        Reverse reverse = new Reverse("test.txt");

        reverse.writeToFile("it is a test text");
        reverse.readFromFile();
        reverse.reverseReadFromFile();

    }
}





Автор: lihusha 14.6.2009, 18:10
мля , как теперь для RandomAccessFile кодировку "UTF-8" выставить ?

Автор: AlexeyVorotnikov 15.6.2009, 10:58
Цитата(lihusha @ 14.6.2009,  19:10)
мля , как теперь для RandomAccessFile кодировку "UTF-8" выставить ?

Никак. RandomAccessFile работает с байтами.

Автор: lihusha 15.6.2009, 19:59
Помогите , плз, с кодировкой .
RandomAccessFile читает , как мне нужно - построчно в обратном порядке , с конца файла , но не могу прочитать из него русские буквы, выдает в одних случаях "?????" , в других - кракозялбы.

Может , кто уже сталкивался с такой стеной.

Автор: Skynin 15.6.2009, 21:00
смотрим http://ru.wikipedia.org/wiki/UTF-8
изучаем java.nio.charset

и выбираем подходы:

1. Читаем побайтно пока не встретим старший утэфовский байт.
Конвертим в символ

2. Читаем побайтно до символа новой строки
Переворачиваем массив
Конвертим в строку

Автор: lihusha 15.6.2009, 21:54
делаю вот так

Код

RandomAccessFile raf = new FandonAccessFile(myFile,"rw");

int read = 0;
String line = null;

for( int i=(int) myFile.length() ; i>=0 ; i--)
{
      raf.seek(i);
      read = raf.read();

       if( (char)read=='\n' )
       {
            line = raf.readLine();
            System.out.println (line);
       }
}




Вот как из строки line получить буквы кириллицы ?

Автор: Skynin 16.6.2009, 11:18
А почему не 
line = raf.readUTF(); http://java.sun.com/javase/6/docs/api/java/io/RandomAccessFile.html?


Автор: lihusha 16.6.2009, 18:06
генерируется исключение

Код

Exception in thread "main" java.io.EOFException

 

причем , генерируется при любых значениях i в выражении

Код


raf.seek(i);



генерируется даже когда в методе делается вызов
 
Код

raf.readUTF();


без 

Код

raf.seek(i);






Автор: Skynin 16.6.2009, 23:14
Цитата(lihusha @ 16.6.2009,  18:06)
генерируется исключение

Потому как в файле - UTF-8?

А если в файле 8битная виндовая кодировка, то сообрази куда вставить, и добавить нехватающего кода:

Код

public CharsetDecoder currCharset;
...
Charset locCharset = Charset.forName("windows-1251");
currCharset = locCharset.newDecoder();


        private String putString(byte[] arrReverse, short realSize) throws CharacterCodingException {
            ByteBuffer lBuff = ByteBuffer.allocate(realSize);
            
            lBuff.put(arrReverse, 0, realSize);
            lBuff.rewind();
    
            return currCharset.decode(lBuff).toString();
        }


    public void reverseReadFromFile() throws FileNotFoundException, IOException {
        System.out.println("Чтение из файла в обратном направлении");

        byte[] arrBt = new byte[999];
        short iarrBt = 0;

        int read = 0;
        long fileLength = file.length();
        for (int i = 1; i <= fileLength; i++) {
            raf.seek(fileLength - i);
            read = raf.read();

    arrBt[iarrBt++] = (byte)read;

    if (read == 10) {
        System.out.println(putString(arrBt,iarrBt));

        iarrBt = 0;
    }
        }
    if (iarrBt > 0)
    System.out.println(putString(arrBt,iarrBt));
        
        System.out.println("\n\n");
    }


Автор: LSD 17.6.2009, 16:54
У меня один вопрос: при чем тут Java: Работа с сетью?

Автор: lihusha 19.6.2009, 19:13
Окончательно у меня получился вот такой класс , который может читать построчно , но с конца текстового файла

Код




import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Arrays;
import java.util.LinkedList;


public class ReverseRead {

    private String filePath;
    private File file;
    private RandomAccessFile reader;
    private FileOutputStream fileOS;
    private OutputStreamWriter writer;

    public ReverseRead(String filePath) throws FileNotFoundException, UnsupportedEncodingException {
        this.filePath = filePath;
        file = new File(filePath);
        fileOS = new FileOutputStream(file, true);
        writer = new OutputStreamWriter(fileOS, "UTF-8");
        reader = new RandomAccessFile(file, "rw");
    }

    public void writeText(String text) throws IOException {
        writer.write(text);
        writer.flush();
        writer.close();
    }
//    метод делает следущее

//    -перемещаясь в цикле с конца файла в начало считывает байты,
//     записывая их во временный LinkedList;
//    -когда позиция считывания доходит до начала строки, массив байтов,
//     полученный из LinkedList, реверсируется, декодируется,из него отсекается
//     ненужное содержимое (~ нули в конце строчки) и этот массив передается в
//     конструктор String,строка выводится на консоль.


    public void readFileInReverse() throws IOException {
        LinkedList<Byte> singleStr = new LinkedList<Byte>();
        Byte read;

        for (int i = (int) file.length() - 1; i >= 0; i--) {
            reader.seek(i);
            read = reader.readByte();
            singleStr.addFirst(read);


            if ((char) read.byteValue() == '\n'|| i==0) {
                if((char) read.byteValue() == '\n')singleStr.pollFirst();
                if (singleStr.size() == 0) {
                    continue;
                }
                byte reverseStr[] = new byte[singleStr.size()];

                for (int j = 0; j < singleStr.size(); j++) {
                    reverseStr[j] = singleStr.get(j).byteValue();

                }
                singleStr = new LinkedList<Byte>();
                Charset charset = Charset.forName("UTF-8");
                CharsetDecoder decoder = charset.newDecoder();
                ByteBuffer buf = ByteBuffer.wrap(reverseStr);


                CharBuffer charBuf = decoder.decode(buf);

                char[] msgBytes = Arrays.copyOf(charBuf.array(), charBuf.limit());
                
                String line = new String(msgBytes);
                System.out.println(line);
            }

            

        }
    }
     public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException, IOException {
        ReverseRead reverse = new ReverseRead("rTest.txt");
        reverse.writeText("первая строчка\nвторая строчка\nтретья строчка");
        reverse.readFileInReverse();

    }
}


Автор: Skynin 19.6.2009, 23:02
абы работало.

А если бы мне понадобилась такая штука в реальный проект, то я бы:
1. вместо LinkedList<Byte> использовал настоящий массив. Увеличивая его, (и копируя старый в увеличенный)
Почитайте внимательно, как работают дженерик типы в Java для объектов и примитивных типов.

2. избавился от операции "переворота массива", незначительным усложнением алгоритма - записывал бы в массив с конца
2а. или вообще перешел бы на функции работы с файлами из пакета java.nio вместо RandomAccessFile чтобы сразу читать в буфер http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html

3. избавился от конструкции:
Код

                char[] msgBytes = Arrays.copyOf(charBuf.array(), charBuf.limit());
                String line = new String(msgBytes);

сведя ее к String line = charBuf.toString();

Автор: lihusha 20.6.2009, 10:41
Skynin, а пример можно ?

Автор: lihusha 28.6.2009, 22:38
нашел метод попроще для чтения файла с конца построчно(начиная с последней строки). Точнее , нашел , как извлечь русские буквы из прочитанной строки

Код

//reader -- RandomAccessFile
String result = new String (reader.readLine().getBytes("ISO-8859-1"),"UTF-8");


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)