Разделить следующую строку на 2:
bf = Entry(Geom, width=5, justify= RIGHT, font="Arial 12").grid(column=1, row=0)
вот так
bf = Entry(Geom, width=5, justify= RIGHT, font="Arial 12")
bf.grid(column=1, row=0)
На данный момент bf
не является виджетом Entry, но None
возвращено из grid()
Также обратите внимание, что обычно вы используете переменную, например IntVar, то есть привязка к виджету входа
Вот трюк: создайте подкласс ObjectOutputStream
и переопределите метод writeStreamHeader
:
public class AppendingObjectOutputStream extends ObjectOutputStream {
public AppendingObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void writeStreamHeader() throws IOException {
// do not write a header, but reset:
// this line added after another question
// showed a problem with the original
reset();
}
}
Чтобы использовать его, просто проверьте, существует ли файл истории или нет и создать экземпляр либо этого добавляемого потока (в случае, если файл существует = мы добавляем = нам не нужен заголовок), либо исходного потока (в случае, если файл не существует = нам нужен заголовок).
Изменить
Я не был доволен первым названием класса. Этот лучше: он описывает «для чего», а не «как это делается».
Изменить
Имя изменено еще раз, чтобы уточнить, что этот поток предназначен только для добавления к существующему файлу. Его нельзя использовать для создания нового файла с данными объекта.
Я расширил принятое решение создать класс, который может использоваться и для добавления и для создания нового файла.
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class AppendableObjectOutputStream extends ObjectOutputStream {
private boolean append;
private boolean initialized;
private DataOutputStream dout;
protected AppendableObjectOutputStream(boolean append) throws IOException, SecurityException {
super();
this.append = append;
this.initialized = true;
}
public AppendableObjectOutputStream(OutputStream out, boolean append) throws IOException {
super(out);
this.append = append;
this.initialized = true;
this.dout = new DataOutputStream(out);
this.writeStreamHeader();
}
@Override
protected void writeStreamHeader() throws IOException {
if (!this.initialized || this.append) return;
if (dout != null) {
dout.writeShort(STREAM_MAGIC);
dout.writeShort(STREAM_VERSION);
}
}
}
Этот класс может использоваться в качестве прямой расширенной замены для ObjectOutputStream. Мы можем использовать класс следующим образом:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ObjectWriter {
public static void main(String[] args) {
File file = new File("file.dat");
boolean append = file.exists(); // if file exists then append, otherwise create new
try (
FileOutputStream fout = new FileOutputStream(file, append);
AppendableObjectOutputStream oout = new AppendableObjectOutputStream(fout, append);
) {
oout.writeObject(...); // replace "..." with serializable object to be written
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Как сказано в API , конструктор ObjectOutputStream
записывает заголовок потока сериализации в базовый поток. Ожидается, что этот заголовок будет только один раз, в начале файла. Таким образом, вызов
new ObjectOutputStream(fos);
несколько раз в FileOutputStream
, который ссылается на один и тот же файл, приведет к многократной записи заголовка и повреждению файла.
ObjectOutputStream
записывает заголовок потока сериализации в базовый поток. И ожидается, что этот заголовок будет только один раз, в начале файла. Таким образом, вызов
new ObjectOutputStream(fos);
несколько раз в FileOutputStream
, который ссылается на один и тот же файл, приведет к многократной записи заголовка и повреждению файла.
ObjectOutputStream
записывает заголовок потока сериализации в базовый поток. И ожидается, что этот заголовок будет только один раз, в начале файла. Таким образом, вызов
new ObjectOutputStream(fos);
несколько раз в FileOutputStream
, который ссылается на один и тот же файл, приведет к многократной записи заголовка и повреждению файла.
Из-за точного формата сериализованного файла добавление действительно повредит его. Вы должны записать все объекты в файл как часть одного и того же потока, иначе произойдет сбой при чтении метаданных потока, когда он ожидает объект.
Вы можете прочитать Спецификацию сериализации , чтобы узнать больше. Детали,
Самый простой способ избежать этой проблемы - оставить OutputStream открытым при написании данные, а не закрывать их после каждого объекта. Вызов reset ()
может быть целесообразным, чтобы избежать утечки памяти.
Альтернативой может быть чтение файла как серии последовательных ObjectInputStreams. Но это требует, чтобы вы подсчитали, сколько байтов вы прочитали (это можно реализовать с помощью FilterInputStream), затем закройте InputStream, откройте его снова, пропустите это количество байтов и только затем заключите его в ObjectInputStream ().