Programmēšana

Izmantojiet RandomAccessFile, lai izveidotu zema līmeņa datu bāzi

Kā es meklēju JavaWorldšī mēneša ideju vietne Soli pa solim, Es uzgāju tikai dažus rakstus, kas aptver zema līmeņa piekļuvi failiem. Lai gan augsta līmeņa API, piemēram, JDBC, mums tiek piešķirta elastība un jauda, ​​kas nepieciešama lielu uzņēmumu lietojumprogrammām, daudzām mazākām lietojumprogrammām ir nepieciešams vienkāršāks un elegants risinājums.

Šajā rakstā mēs izveidosim paplašinājumu RandomAccessFile klase, kas ļauj mums saglabāt un izgūt ierakstus. Šis "ierakstu fails" būs līdzvērtīgs pastāvīgai hashtable, ļaujot atslēgas objektus uzglabāt un izgūt no failu krātuves.

Primer failiem un ierakstiem

Pirms ķeramies pie galvas piemērā, sāksim ar pamata backgrounder. Sāksim, definējot dažus terminus, kas attiecas uz failiem un ierakstiem, pēc tam īsi apspriedīsim klasi java.io.RandomAccessFile un atkarība no platformas.

Terminoloģija

Šīs definīcijas ir pielāgotas mūsu piemēram, nevis tradicionālajai datu bāzes terminoloģijai.

Ieraksts - Failā saglabāto saistīto datu kolekcija. Ierakstam parasti ir vairāki lauki, katrs no tiem ir nosaukts un ierakstīts informācijas elements.

Atslēga - ieraksta identifikators. Atslēgas parasti ir unikālas.

Fails - secīga datu apkopošana, kas tiek glabāta kaut kādā stabilā krātuvē, piemēram, cietajā diskā.

Nav būtiska piekļuve failiem - Ļauj datus nolasīt no patvaļīgām faila vietām.

Faila rādītājs - skaitlis, kas tur nākamā datu baita pozīciju, kas jāizlasa no faila.

Ieraksta rādītājs - Ieraksta rādītājs ir faila rādītājs, kas norāda uz vietu, kur sākas konkrēts ieraksts.

Indekss - sekundārs veids, kā piekļūt ierakstiem failā; tas ir, tas kartē atslēgas, lai ierakstītu rādītājus.

Kaudze - secīgs fails no nesakārtotiem un mainīga lieluma ierakstiem. Kaudzei ir nepieciešama ārēja indeksēšana, lai jēgpilni piekļūtu ierakstiem.

Neatlaidība - attiecas uz objekta vai ieraksta glabāšanu uz noteiktu laiku. Šis laika periods parasti ir garāks nekā viena procesa posms, tāpēc objekti parasti ir pastāvēja datnēs vai datubāzēs.

Klases java.io.RandomAccessFile pārskats

Klase RandomAccessFile ir Java veids, kā nodrošināt nenozīmīgu piekļuvi failiem. Klase ļauj mums pāriet uz noteiktu vietu failā, izmantojot meklēt () metodi. Kad faila rādītājs ir novietots, datus var nolasīt un ierakstīt failā, izmantojot DataInput un DataOutput saskarnes. Šīs saskarnes ļauj mums lasīt un rakstīt datus neatkarīgi no platformas. Citas ērtas metodes RandomAccessFile ļauj mums pārbaudīt un iestatīt faila garumu.

Apsvērumi, kas atkarīgi no platformas

Mūsdienu datu bāzes glabāšanai ir atkarīgas no diskdziņiem. Diska diska dati tiek saglabāti mapē bloki, kas ir sadalīti pa visām pusēm dziesmas un virsmām. Disks meklēt laiku un rotācijas kavēšanās diktē, kā visefektīvāk saglabāt un iegūt datus. Tipiska datu bāzes pārvaldības sistēma cieši balstās uz diska atribūtiem, lai pilnveidotu veiktspēju. Diemžēl (vai par laimi, atkarībā no jūsu interesēm par zema līmeņa failu I / O!), Šie parametri ir tālu no sasniedzamības, izmantojot augsta līmeņa failu API, piemēram, java.io. Ņemot vērā šo faktu, mūsu piemērā netiks ņemtas vērā optimizācijas, kuras varētu sniegt zināšanas par diska parametriem.

RecordsFile piemēra noformēšana

Tagad mēs esam gatavi izstrādāt savu piemēru. Lai sāktu, es izklāstīšu dažas dizaina prasības un mērķus, atrisinās vienlaicīgas piekļuves jautājumus un norādīšu zema līmeņa faila formātu. Pirms turpināt īstenošanu, mēs apskatīsim arī galvenās ierakstu darbības un tām atbilstošos algoritmus.

Prasības un mērķi

Mūsu galvenais mērķis šajā piemērā ir izmantot a RandomAccessFile nodrošināt ierakstu datu glabāšanas un izguves veidu. Mēs saistīsim veida atslēgu Stīga ar katru ierakstu kā līdzekli tā unikālai identificēšanai. Taustiņi tiks ierobežoti līdz maksimālajam garumam, lai gan ieraksta dati netiks ierobežoti. Šajā piemērā mūsu ieraksti sastāvēs tikai no viena lauka - bināro datu "lāse". Faila kods nemēģinās jebkādā veidā interpretēt ieraksta datus.

Kā otro dizaina mērķi mēs pieprasīsim, lai izveidošanas laikā netiktu fiksēts mūsu failu atbalstīto ierakstu skaits. Mēs ļausim failam augt un sarukt, kad ieraksti tiek ievietoti un noņemti. Tā kā mūsu indeksa un ierakstu dati tiks glabāti vienā failā, šis ierobežojums liks mums pievienot papildu loģiku, lai dinamiski palielinātu indeksa vietu, reorganizējot ierakstus.

Piekļuve datiem failā ir pakāpes lēnāka nekā piekļuve datiem atmiņā. Tas nozīmē, ka datplūsmas veikto piekļuves failu skaits būs noteicošais veiktspējas faktors. Mēs pieprasīsim, lai mūsu galvenās datu bāzes darbības nebūtu atkarīgas no failā esošo ierakstu skaita. Citiem vārdiem sakot, tie būs ar nemainīgu pasūtījuma laiku attiecībā uz piekļuvi failiem.

Kā pēdējo prasību mēs pieņemsim, ka mūsu indekss ir pietiekami mazs, lai to ielādētu atmiņā. Tas mūsu ieviešanai atvieglos prasības izpildi, kas nosaka piekļuves laiku. Mēs atspoguļosim indeksu a Hashtable, kas nodrošina tūlītēju ierakstu galvenes meklēšanu.

Kodu labošana

Šī raksta kodā ir kļūda, kuras dēļ tas daudzos iespējamos gadījumos rada NullPointerException. Abstraktajā klasē BaseRecordsFile ir rutīna ar nosaukumu insureIndexSpace (int). Kods ir paredzēts esošo ierakstu pārvietošanai uz faila beigām, ja nepieciešams paplašināt indeksa apgabalu. Pēc "pirmā" ieraksta jaudas atiestatīšanas uz tā faktisko lielumu tas tiek pārvietots uz beigām. Tad dataStartPtr tiek iestatīts norādīt uz otro faila ierakstu. Diemžēl, ja pirmajā ierakstā bija brīva vieta, jaunais dataStartPtr nenorādīs uz derīgu ierakstu, jo to palielināja pirmā ieraksta garums nevis tā ietilpība. Modificētais Java avots programmai BaseRecordsFile ir atrodams vietnē Resursi.

no Rona Volkopa

Vecākais programmatūras inženieris

bioMerieux, Inc.

Sinhronizācija un vienlaicīga piekļuve failiem

Vienkāršības labad mēs vispirms atbalstām tikai viena pavediena modeli, kurā failu pieprasījumi ir aizliegti vienlaikus. Mēs to varam paveikt, sinhronizējot programmas publiskās piekļuves metodes BaseRecordsFile un RecordsFile klases. Ņemiet vērā, ka varat atvieglot šo ierobežojumu, lai pievienotu atbalstu vienlaicīgai lasīšanai un rakstīšanai nekonfliktējošos ierakstos. Jums būs jāuztur bloķēto ierakstu saraksts un jāpapildina lasījumi un rakstīšana vienlaikus pieprasījumiem.

Sīkāka informācija par faila formātu

Tagad mēs skaidri definēsim ierakstu faila formātu. Fails sastāv no trim reģioniem, katram no kuriem ir savs formāts.

Faila galvenes reģions. Šajā pirmajā reģionā ir divas būtiskas galvenes, kas nepieciešamas, lai piekļūtu mūsu faila ierakstiem. Pirmais galvenes nosaukums datu sākuma rādītājs, ir ilgi kas norāda uz ieraksta datu sākumu. Šī vērtība norāda indeksa reģiona lielumu. Otrais galvenes nosaukums ierakstu galvene, ir int kas norāda ierakstu skaitu datu bāzē. Galvenes reģions sākas ar faila pirmo baitu un paplašinās uz FILE_HEADERS_REGION_LENGTH baiti. Mēs izmantosim readLong () un readInt () lasīt galvenes un writeLong () un writeInt () rakstīt galvenes.

Indeksa reģions. Katrs ieraksts indeksā sastāv no atslēgas un ieraksta galvenes. Indekss sākas ar pirmo baitu pēc faila galvenes reģiona un stiepjas līdz baitam pirms datu sākuma rādītāja. Pēc šīs informācijas mēs varam aprēķināt faila rādītāju uz jebkura no sākumiem n ieraksti indeksā. Ierakstiem ir noteikts garums - galvenie dati sākas ar pirmo baitu indeksa ierakstā un paplašinās MAX_KEY_LENGTH baiti. Attiecīgā ieraksta galvene konkrētai atslēgai seko tūlīt aiz atslēgas indeksā. Ieraksta galvene mums norāda, kur atrodas dati, cik baitu ieraksts var turēt un cik baitus tas faktiski glabā. Indeksa ieraksti faila rādītājā nav noteiktā secībā, un tie nav saistīti ar secību, kādā ieraksti tiek glabāti failā.

Ierakstīt datu reģionu. Ieraksta datu reģions sākas vietā, kuru norāda datu sākuma rādītājs, un stiepjas līdz faila beigām. Ieraksti failā tiek novietoti atpakaļ un atpakaļ, un starp ierakstiem nav atļauta brīva vieta. Šī faila daļa sastāv no neapstrādātiem datiem bez galvenes vai galvenās informācijas. Datu bāzes fails beidzas faila pēdējā ieraksta pēdējā blokā, tāpēc faila beigās nav papildu vietas. Fails pieaug un samazinās, kad tiek pievienoti un dzēsti ieraksti.

Ierakstam piešķirtais lielums ne vienmēr atbilst faktiskajam datu apjomam, kuru ieraksts satur. Ierakstu var uzskatīt par konteineru - tas var būt tikai daļēji pilns. Derīgi ieraksta dati tiek novietoti ieraksta sākumā.

Atbalstītās darbības un to algoritmi

The RecordsFile atbalstīs šādas galvenās darbības:

  • Ievietot - failam pievieno jaunu ierakstu

  • Lasīt - nolasa ierakstu no faila

  • Atjaunināt - atjaunina ierakstu

  • Dzēst - izdzēš ierakstu

  • Nodrošināt kapacitāti - palielina indeksa reģionu, lai uzņemtu jaunus ierakstus

Pirms iziet avota kodu, apskatīsim izvēlētos algoritmus katrai no šīm darbībām:

Ievietojiet. Šī darbība ievieto failā jaunu ierakstu. Lai ievietotu, mēs:

  1. Pārliecinieties, vai ievietotā atslēga jau nav failā
  2. Pārliecinieties, vai indeksa reģions ir pietiekami liels, lai varētu ievadīt papildu
  3. Atrodiet failā brīvu vietu, kas ir pietiekami liela, lai turētu ierakstu
  4. Ierakstiet ieraksta datus failā
  5. Pievienojiet ieraksta galveni indeksam

Lasīt. Šī darbība izgūst pieprasīto ierakstu no faila, pamatojoties uz atslēgu. Lai izgūtu ierakstu, mēs:

  1. Izmantojiet indeksu, lai norādīto atslēgu piesaistītu ieraksta galvenei
  2. Meklēt līdz datu sākumam (izmantojot rādītāju galvenē saglabātajiem ieraksta datiem)
  3. Izlasiet ieraksta datus no faila

Atjaunināt. Šī darbība atjaunina esošo ierakstu ar jauniem datiem, aizstājot jaunos datus ar vecajiem. Mūsu atjaunināšanas darbības atšķiras atkarībā no jaunā ieraksta datu lieluma. Ja jaunie dati iekļaujas esošajā ierakstā, mēs:

  1. Ierakstiet ieraksta datus failā, pārrakstot iepriekšējos datus
  2. Atjauniniet atribūtu, kas ieraksta galvenē satur datu garumu

Pretējā gadījumā, ja dati ir pārāk lieli ierakstam, mēs:

  1. Veiciet esošā ieraksta dzēšanas darbību
  2. Veiciet jauno datu ievietošanu

Dzēst. Šī darbība noņem no faila ierakstu. Lai izdzēstu ierakstu, mēs:

  1. Pieprasiet noņemamajam ierakstam atvēlēto vietu, vai nu samazinot failu, ja ieraksts ir pēdējais failā, vai arī pievienojot tā vietu blakus esošajam ierakstam

  2. Noņemiet ieraksta galveni no indeksa, dzēšamo ierakstu aizstājot ar pēdējo indeksa ierakstu; tas nodrošina, ka indekss vienmēr ir pilns un starp ierakstiem nav tukšu atstarpju

Nodrošiniet jaudu. Šī darbība nodrošina, ka indeksa reģions ir pietiekami liels, lai tajā varētu ievietot papildu ierakstus. Cilpā mēs pārvietojam ierakstus no faila priekšpuses līdz beigām, līdz ir pietiekami daudz vietas. Lai pārvietotu vienu ierakstu, mēs:

  1. Atrodiet faila pirmā ieraksta ieraksta galveni; ņemiet vērā, ka šis ir ieraksts ar datiem ieraksta datu reģiona augšdaļā, nevis ieraksts ar pirmo galveni indeksā

  2. Izlasiet mērķa ieraksta datus

  3. Palieliniet failu pēc mērķa ieraksta datu lieluma, izmantojot setLength (garš) metode RandomAccessFile

  4. Ierakstiet ieraksta datus faila apakšdaļā

  5. Atjauniniet pārvietoto ierakstu datu rādītāju

  6. Atjauniniet globālo galveni, kas norāda uz pirmā ieraksta datiem

Detalizēta informācija par ieviešanu - pārejiet uz avota kodu

Tagad mēs esam gatavi sasmērēt rokas un izskatīt piemērā redzamo kodu. Pilnu avotu varat lejupielādēt no resursiem.

Piezīme. Avota sastādīšanai jāizmanto Java 2 platforma (agrāk pazīstama kā JDK 1.2).

Klases BaseRecordsFile

BaseRecordsFile ir abstrakta klase un ir mūsu piemēra galvenā realizācija. Tas nosaka galvenās piekļuves metodes, kā arī virkni noderīgu metožu, lai manipulētu ar ierakstiem un indeksa ierakstiem.

$config[zx-auto] not found$config[zx-overlay] not found