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


Автор: Goliath 17.4.2006, 23:56
Доброго времени суток есть вопрос по чтению файлов. Есть ли в Java возможность читать файл как в Delphi или С++ ниже привожу пример.

Код

THeader = Record
    ID : Array[1..4] of Char;         
    Filename      : Array[1..68] of Char;
 end;
.......

 Header     : THeader ;
.......
  AssignFile(F, filename);
  Reset(F,1);

  BlockRead(F, Header, Sizeof(Header));
 

Автор: powerOn 18.4.2006, 08:19
В Java нет структур. В Java есть классы, и хотя по смыслу и похожие вещи, но реализованны по разному.
В Dephi и C++ так можно делать поскольку в памяти структура представляет собой непрерывный диапазон ячеек. Чтобы туда данные записать достаточно знать начальный адрес. Поля потом читываться будут по смещению от начального адреса структуры.

Java более высокоуровневый язык и не оперирует указателями. Поэтому, думаю, что способов подобного чтения нет.  smile  Хотя сериализация должна отлично все заменить.  smile 


   

Автор: ALKS 18.4.2006, 14:40
Не понимаю сути вопроса. какая разница как читать фаил? тебе нужно прочитать фаил в память? - в ява есть  море способов это сделать. да по другому. ну и что? главное ведь результат.
 

Автор: COVD 18.4.2006, 15:23
Цитата

Хотя сериализация должна отлично все заменить


Не совсем так. Сериализация пишет в виде пар: параметр=значение. Чем длинней имена переменных, тем длинней файл. Структура - это одни голые значения. Поэтому такой файл придется читать по байтам или использовать методы типа readInt(), readFloat(). Фактически вручную выковыривать данные. 

Автор: garm 18.4.2006, 16:19
Цитата(COVD @  18.4.2006,  19:23 Найти цитируемый пост)
 Сериализация пишет в виде пар: параметр=значение.

На самом деле там всё немножко хитрее устроено. Когда мы первый раз пишем объект в поток, сохраняются данные о классе, в том числе и имена полей. А потом идут значения этих полей, в том же порядке, в каком шли их имена. Если же мы пишем ещё один объект того же класса, то там ставится ссылка на уже записанное определение, а потом идут значения полей.
Так что если мы сохраняем много объектов одного и того же класса, накладные расходы будут не очень велики. Хотя, конечно, будут. 

Автор: Goliath 18.4.2006, 19:02
Всем спасибо. Просто удобно так считывать данные. Придется самому писать. 

Автор: LSD 18.4.2006, 20:57
Цитата(garm @  18.4.2006,  17:19 Найти цитируемый пост)
На самом деле там всё немножко хитрее устроено....

На самом деле там еще хитрей все устроено smile
Имена полей не пишутся вообще. Вначале идет заголовок потока (он один на всю сессию записи), потом полное имя класса или указание что это примитивный тип или строка, затем SerialVersionUID (прописанный явно или вычисленный), а затем поля (поля при записи сортируются).


Goliath, на самом деле накладные расходы на объект составляют порядка 10-30 байт. Если это приемлемо, то сериализация неплохой вариант. И еще есть вариант, реализовать интерфейс Externalizable и самому управлять процессом сохранения.  

Автор: COVD 18.4.2006, 21:17
Цитата

Имена полей не пишутся вообще

по идее не должны, однако видел я эти имена, когда обьект писался в ObjectOutputStream и выводился байтовый массив.   

Автор: Bozo 18.4.2006, 22:46
Код

1. import java.io.*;
  2. import java.util.*;
  3.
  4. public class DataFileTest
  5. {
  6.   public static void main(String[] args)
  7.   {
  8.      Employee[] staff = new Employee[3];
  9.
 10.      staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
 11.      staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
 12.      staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);
 13.
 14.      try
 15.      {
 16.         // save all employee records to the file employee.dat
 17.         PrintWriter out = new PrintWriter(new FileWriter("employee.dat"));
 18.         writeData(staff, out);
 19.         out.close();
 20.
 21.         // retrieve all records into a new array
 22.         BufferedReader in = new BufferedReader(new  FileReader("employee.dat"));
 23.         Employee[] newStaff = readData(in);
 24.         in.close();
 25.
 26.         // print the newly read employee records
 27.         for (Employee e : newStaff)
 28.            System.out.println(e);
 29.      }
 30.      catch(IOException exception)
 31.      {
 32.         exception.printStackTrace();
 33.      }
 34.   }
 35.
 36.   /**
 37.      Writes all employees in an array to a print writer
 38.      @param employees an array of employees
 39.      @param out a print writer
 40.   */
 41.   static void writeData(Employee[] employees, PrintWriter out)
 42.      throws IOException
 43.   {
 44.      // write number of employees
 45.      out.println(employees.length);
 46.
 47.      for (Employee e : employees)
 48.         e.writeData(out);
 49.   }
 50.
 51.   /**
 52.      Reads an array of employees from a buffered reader
 53.      @param in the buffered reader
 54.      @return the array of employees
 55.   */
 56.   static Employee[] readData(BufferedReader in)
 57.      throws IOException
 58.   {
 59.      // retrieve the array size
 60.      int n = Integer.parseInt(in.readLine());
 61.
 62.      Employee[] employees = new Employee[n];
 63.      for (int i = 0; i < n; i++)
 64.      {
 65.         employees[i] = new Employee();
 66.         employees[i].readData(in);
 67.      }
 68.      return employees;
 69.   }
 70. }
 71.
 72. class Employee
 73. {
 74.    public Employee() {}
 75.
 76.    public Employee(String n, double s, int year, int month, int day)
 77.    {
 78.       name = n;
 79.       salary = s;
 80.       GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
 81.       hireDay = calendar.getTime();
 82.    }
 83.
 84.    public String getName()
 85.    {
 86.       return name;
 87.    }
 88.
 89.    public double getSalary()
 90.    {
 91.       return salary;
 92.    }
 93.
 94.    public Date getHireDay()
 95.    {
 96.       return hireDay;
 97.    }
 98.
 99.    public void raiseSalary(double byPercent)
100.    {
101.       double raise = salary * byPercent / 100;
102.       salary += raise;
103.    }
104.
105.    public String toString()
106.    {
107.       return getClass().getName()
108.          + "[name=" + name
109.          + ",salary=" + salary
110.          + ",hireDay=" + hireDay
111.          + "]";
112.    }
113.
114.    /**
115.       Writes employee data to a print writer
116.       @param out the print writer
117.   */
118.   public void writeData(PrintWriter out) throws IOException
119.   {
120.      GregorianCalendar calendar = new GregorianCalendar();
121.      calendar.setTime(hireDay);
122.      out.println(name + "|"
123.         + salary + "|"
124.         + calendar.get(Calendar.YEAR) + "|"
125.         + (calendar.get(Calendar.MONTH) + 1) + "|"
126.         + calendar.get(Calendar.DAY_OF_MONTH));
127.   }
128.
129.   /**
130.      Reads employee data from a buffered reader
131.      @param in the buffered reader
132.   */
133.   public void readData(BufferedReader in) throws IOException
134.   {
135.      String s = in.readLine();
136.      StringTokenizer t = new StringTokenizer(s, "|");
137.      name = t.nextToken();
138.      salary = Double.parseDouble(t.nextToken());
139.      int y = Integer.parseInt(t.nextToken());
140.      int m = Integer.parseInt(t.nextToken());
141.      int d = Integer.parseInt(t.nextToken());
142.      GregorianCalendar calendar = new GregorianCalendar(y, m - 1, d);
143.      hireDay = calendar.getTime();
144.   }
145.
146.   private String name;
147.   private double salary;
148.   private Date hireDay;
149. }
 

Автор: ALKS 18.4.2006, 22:53
Цитата(LSD @  18.4.2006,  20:57 Найти цитируемый пост)
Goliath, на самом деле накладные расходы на объект составляют порядка 10-30 байт. Если это приемлемо, то сериализация неплохой вариант. И еще есть вариант, реализовать интерфейс Externalizable и самому управлять процессом сохранения.  


у нас один процесс гдузит в память данные сериализациeй. сериализрованный заранее в фаил объект весьма не простой структуры. фаил около 300Mb. грузиться в памявть за пару десятков секунд на довольно средней машине. вы будете смеяться но после ряда эксперементов это оказался самый быстрый способ загрузки... 

Автор: garm 19.4.2006, 10:30
Цитата(LSD @  19.4.2006,  00:57 Найти цитируемый пост)
Имена полей не пишутся вообще.

Вот и мне интересно, если имена не пишутся, то откуда они берутся в потоке?
Я сохранял объекты в файл и тоже имел удовольствие наблюдать имена полей.  

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