Baca dan Tulis ke File Biner?

Saya menyimpan beberapa kelas Objek yang dibuat khusus (Streaming data) ke File.

Saya harus dapat memuat konten File ke dalam TStringList sehingga saya dapat menambahkan baris baru di akhir File, dan kemudian Menyimpan perubahannya.

Ini tidak berfungsi karena LoadFromFile sepertinya tidak dapat mengurai File dengan benar. Saya berasumsi karena karakter lucu yang digunakan Stream Saves to File, dan TStringList mengharapkan informasi tekstual biasa.

Bagaimana saya bisa melakukan hal berikut:

  • Baca File Biner Mentah apa pun ke dalam TStringList.
  • Tambahkan Baris baru saya, misalnya StringList1.Add(MyString);
  • Simpan kembali File Biner Mentah.

Pertanyaan ini sebenarnya berkaitan dengan pertanyaan lain yang saya ajukan: Menyimpan nilai CRC dalam file, tanpa mengubah Checksum CRC yang sebenarnya?

Inilah yang saya coba lakukan:

  • Hitung Checksum CRC dari File Streaming Tersimpan saya.
  • Tambahkan Nilai CRC ke akhir File.
  • Simpan kembali File.

Kemudian ketika saya mencoba Membuka File Streaming saya:

  • Tetapkan Nilai CRC (di akhir File) ke variabel.
  • Hapus Nilai CRC dari File.
  • Simpan File Streaming sebagai File Temp baru.
  • Hitung dan Bandingkan CRC File Temp, dengan CRC yang disimpan dalam variabel.
  • Jika CRC File cocok dengan Nilai CRC yang disimpan internal, saya dapat memproses File seperti biasa.

Tapi saya tidak tahu cara Membaca atau Menulis Data Biner Mentah dari File.

Saya akan berterima kasih jika seseorang bisa memberi saya bantuan dan saran, terima kasih :)


person Community    schedule 23.12.2011    source sumber
comment
Anda menyimpan checksum ke dalam file teks? Apakah itu benar? Saya masih tidak mengerti mengapa Anda memerlukan checksum.   -  person David Heffernan    schedule 23.12.2011
comment
Menyimpan ke File Streaming, saya melakukan ini sehingga setiap kali File dibuka dari Aplikasi saya, saya dapat menentukan apakah sebenarnya File tersebut awalnya disimpan dari program saya.   -  person    schedule 23.12.2011
comment
Apakah Anda ingin file dapat dibaca di editor teks? FWIW pendekatan Anda saat ini sangat boros dengan pembacaan dan penulisan palsu.   -  person David Heffernan    schedule 23.12.2011
comment
Versi Delphi apa yang Anda gunakan? Ini penting khususnya untuk string Unicode (atau tidak)   -  person David Heffernan    schedule 23.12.2011
comment
Ini tidak masuk akal. Mungkin Anda harus menyatakan lebih banyak tentang apa yang sebenarnya ingin Anda lakukan dengan file biner ini. Secara pribadi menurut saya Anda tidak harus menggunakan TStringList untuk menyimpan data biner. Bagaimana Anda ingin memutuskan apa itu baris baru (carriage return + linefeed yang setara? Atau apakah Anda akan memuat satu blok data (katakanlah 1024 byte) per item di BinaryStringList?   -  person Warren P    schedule 23.12.2011
comment
Saya menggunakan Delphi XE. File disimpan sebagai Stream dan karena itu tidak dapat dibaca, itu tidak masalah. Saya tidak perlu mengedit File di luar program saya, justru sebaliknya. Saya hanya perlu menambahkan baris yang berisi CRC File untuk mengakhiri, tetapi ini tidak berfungsi karena saya tidak dapat membaca File. Saya rasa saya mengacaukan semuanya lagi dan membuat situasi sulit dari sesuatu yang sederhana.   -  person    schedule 23.12.2011
comment
File biner tidak memiliki baris, jadi Anda tidak dapat menambahkannya.   -  person Uwe Raabe    schedule 23.12.2011
comment
Menurut pendapat saya, Anda membuat hidup menjadi sulit bagi diri Anda sendiri. Saya tidak dapat membayangkan mengapa Anda ingin mempersulit Anda membaca dan menulis file. Sulit bagi pengguna untuk mengotomatiskan aplikasi. Dan berisiko jika Anda perlu mengubah format file. Jika Anda harus melakukan hal seperti ini, letakkan di file lain dengan nama dasar yang cocok dengan file teks. Anda terlalu memperumit dan mencoba memecahkan masalah yang tidak ada.   -  person David Heffernan    schedule 23.12.2011
comment
Jika saya mencoba membuka File yang disimpan dari program saya dan file tersebut rusak (misalnya aliran dalam file rusak) program masih mencoba membuka file aliran meskipun tidak bisa, mungkin tertulis Memori Habis error misalnya, atau terkadang tidak ada sama sekali. Coba..Kecuali blok sepertinya tidak menyadari bahwa file tidak dapat dibuka dan tidak memunculkan pengecualian. Jadi saya pikir saya bisa memasukkan nilai checksum CRC file secara internal dan memeriksa integritas file dengan cara itu. Tapi ya, sepertinya aku mempersulit diriku sendiri.   -  person    schedule 23.12.2011
comment
Akan lebih baik jika mendeteksi file yang rusak dan melaporkan kesalahan. Jika pengguna mengacaukan file maka itu masalahnya. Simpan di bawah profil pengguna mereka dan tidak ada alasan bagi mereka untuk mengacaukannya.   -  person David Heffernan    schedule 23.12.2011
comment
Ini bukan file yang bisa saya sembunyikan di direktori temp, karena dapat dimuat dari TOpenDialog. Saya setuju jika ada yang memutuskan untuk mengacaukan file yang merupakan kesalahan mereka sendiri, tetapi untuk beberapa alasan saya tidak dapat menjebak kesalahan jika file (aliran data) rusak - hampir selalu tidak menunjukkan kesalahan tetapi tetap mencoba memprosesnya.   -  person    schedule 23.12.2011
comment
Saya pikir saya menyelesaikannya, dan untuk kali ini dengan tidak menciptakan lebih banyak masalah daripada yang diperlukan! Saya mencoba menangkap pengecualian dalam prosedur saya yang Membuka File, sebagai gantinya saya membuat blok coba..pengecualian di kelas dasar sebenarnya tempat saya memuat aliran, jika ada pengecualian saya menetapkan tanda boolean untuk memberi tahu saya jika file dimuat dengan baik. Saya memeriksa tanda ini dalam prosedur Buka dan dapat menentukan apakah file tersebut baik-baik saja atau tidak. tampaknya bekerja dengan cara ini. Aku tak mengerti kenapa aku bingung dan membuat masalah semakin sulit :(   -  person    schedule 23.12.2011
comment
Craig; Tip gratis; File biner adalah masalah. Jika Anda tidak perlu membuat format file biner khusus, jangan lakukan itu. File teks jauh lebih tangguh dan dapat diandalkan, serta lebih mudah dipecahkan jika terjadi kesalahan format.   -  person Warren P    schedule 23.12.2011
comment
Warren, terima kasih atas tipnya. Saya mungkin mempertimbangkan untuk mengubah cara saya menyimpan objek ke file, mungkin XML akan menjadi pilihan yang lebih baik.   -  person    schedule 24.12.2011
comment
@Craig XML akan menjadi salah satu pilihan yang baik. JSON jauh lebih mudah dibaca jika Anda ingin manusia menguraikannya. Secara pribadi favorit saya adalah YAML tapi itu memerlukan banyak usaha untuk masuk ke Delphi. JSON atau XML adalah pilihan yang bagus.   -  person David Heffernan    schedule 24.12.2011
comment
@David Saya tidak tahu apa-apa tentang format file JSON atau YAML tanpa membacanya. Saya telah membaca lebih banyak tentang XML dan saya melihat penerapannya tidak akan terlalu merepotkan. Saya tidak terlalu menyukai cara Streams menyimpan ke File, dan seperti yang Anda katakan, setidaknya sesuatu seperti XML akan memungkinkan keterbacaan jika diinginkan.   -  person    schedule 25.12.2011
comment
Parser XML manakah yang ingin Anda gunakan?   -  person David Heffernan    schedule 25.12.2011
comment
Saya berpikir untuk menggunakan TXMLDocument, dan menyimpan objek saya sebagai node XML.   -  person    schedule 26.12.2011


Jawaban (1)


Kelas ini diturunkan dari TStringList dan menambahkan nilai centang di akhir saat menulis ke file. Nilai ini diperiksa setiap kali file dibaca.

type
  TCRCStringList = class(TStringList)
  type
    TCRC = LongWord;
  private
    function CalcCRC(Stream: TStream): TCRC;
  public
    procedure LoadFromStream(Stream: TStream; Encoding: TEncoding); override;
    procedure SaveToStream(Stream: TStream; Encoding: TEncoding); override;
  end;

function TCRCStringList.CalcCRC(Stream: TStream): TCRC;
begin
  Result := 42;  // place CRC calculation here
end;

procedure TCRCStringList.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
  crc: TCRC;
  temp: TMemoryStream;
begin
  temp := TMemoryStream.Create;
  try
    temp.CopyFrom(Stream, Stream.Size - Sizeof(crc));
    Stream.Read(crc, Sizeof(crc));
    if crc <> CalcCRC(temp) then
      raise Exception.Create('CRC error');
    temp.Position := 0;
    inherited LoadFromStream(temp, Encoding);
  finally
    temp.Free;
  end;
end;

procedure TCRCStringList.SaveToStream(Stream: TStream; Encoding: TEncoding);
var
  crc: TCRC;
  temp: TMemoryStream;
begin
  temp := TMemoryStream.Create;
  try
    inherited SaveToStream(temp, Encoding);
    temp.Position := 0;
    crc := CalcCRC(temp);
    temp.Position := temp.Size;
    temp.Write(crc, Sizeof(crc));
    Stream.CopyFrom(temp, 0); // count = 0 copies the whole stream from the beginning
  finally
    temp.Free;
  end;
end;
person Uwe Raabe    schedule 23.12.2011
comment
terima kasih telah memposting, kode Anda terlihat menarik. Saya telah menyelesaikan masalah awal saya tanpa menggunakan pemeriksaan CRC apa pun. Saya akan menerima jawaban Anda karena tampaknya sangat berguna, saya harus melihatnya lebih dekat untuk menelitinya. Terima kasih - person ; 23.12.2011