Programmēšana

Notiek komandrindas argumentu apstrāde Java: lieta slēgta

Daudzas Java lietojumprogrammas, kas sāktas no komandrindas, prasa argumentus, lai kontrolētu viņu uzvedību. Šie argumenti ir pieejami virknes masīva argumentā, kas tiek ievadīts lietojumprogrammas statikā galvenais () metodi. Parasti ir divu veidu argumenti: opcijas (vai slēdži) un faktisko datu argumenti. Java lietojumprogrammai ir jāapstrādā šie argumenti un jāveic divi pamatuzdevumi:

  1. Pārbaudiet, vai izmantotā sintakse ir derīga un atbalstīta
  2. Iegūstiet faktiskos datus, kas nepieciešami lietojumprogrammas darbību veikšanai

Bieži vien kods, kas veic šos uzdevumus, tiek pielāgots katrai lietojumprogrammai, un tāpēc tā izveide un uzturēšana prasa ievērojamas pūles, it īpaši, ja prasības pārsniedz vienkāršus gadījumus tikai ar vienu vai divām iespējām. The Iespējas Šajā rakstā aprakstītā klase īsteno vispārēju pieeju, lai viegli tiktu galā ar vissarežģītākajām situācijām. Klase ļauj vienkārši definēt nepieciešamās opcijas un datu argumentus, kā arī nodrošina rūpīgas sintakses pārbaudes un ērtu piekļuvi šo pārbaužu rezultātiem. Šajā projektā tika izmantotas arī jaunas Java 5 funkcijas, piemēram, ģenerikas un tipogrāfijas.

Komandrindas argumentu veidi

Gadu gaitā esmu uzrakstījis vairākus Java rīkus, kas izmanto komandrindas argumentus, lai kontrolētu viņu uzvedību. Sākumā es uzskatu, ka ir nepatīkami manuāli izveidot un uzturēt kodu dažādu iespēju apstrādei. Tas noveda pie prototipa klases izstrādes, lai atvieglotu šo uzdevumu, taču šai klasei, protams, bija ierobežojumi, jo, rūpīgi pārbaudot, iespējamo dažādu variantu skaits komandrindas argumentiem izrādījās ievērojams. Galu galā es nolēmu izstrādāt vispārēju šīs problēmas risinājumu.

Izstrādājot šo risinājumu, man bija jāatrisina divas galvenās problēmas:

  1. Norādiet visas šķirnes, kurās var parādīties komandrindas opcijas
  2. Atrodiet vienkāršu veidu, kā ļaut lietotājiem izteikt šīs šķirnes, izmantojot vēl izstrādājamo klasi

Analizējot 1. problēmu, tika iegūti šādi novērojumi:

  • Komandrindas opcijas pretēji komandrindas datu argumentiem - sāciet ar prefiksu, kas tos unikāli identificē. Prefiksu piemēri ietver domuzīmi (-) Unix platformās tādām opcijām kā -a vai slīpsvītru (/) Windows platformās.
  • Opcijas var būt vai nu vienkārši slēdži (t.i., -a var būt klāt vai nē) vai ņemt vērtību. Piemērs ir:

    java MyTool -a -b logfile.inp 
  • Opcijām, kas ņem vērtību, faktiskajam izvēles taustiņam un vērtībai var būt dažādi atdalītāji. Šādi atdalītāji var būt tukša vieta, kols (:) vai vienādības zīme (=):

    java MyTool -a -b logfile.inp java MyTool -a -b: logfile.inp java MyTool -a -b = logfile.inp 
  • Opcijas, kurām ir vērtība, var pievienot vēl vienu sarežģītības pakāpi. Apsveriet, kā Java atbalsta vides īpašību definīciju kā piemēru:

    java -Djava.library.path = / usr / lib ... 
  • Tātad, ārpus faktiskās opcijas taustiņa (D), atdalītājs (=) un opcijas faktiskā vērtība (/ usr / lib), papildu parametrs (java.library.path) var iegūt jebkuru vērtību skaitu (iepriekš minētajā piemērā, izmantojot šo sintaksi, var norādīt daudzas vides īpašības). Šajā rakstā šo parametru sauc par "detaļu".
  • Opcijām ir arī daudzkārtības īpašība: tās var būt obligātas vai neobligātas, un atļauto reižu skaits var arī atšķirties (piemēram, tieši vienu, vienu vai vairākas reizes vai citas iespējas).
  • Datu argumenti ir visi komandrindas argumenti, kas nesākas ar prefiksu. Šeit pieņemamais šādu datu argumentu skaits var atšķirties starp minimālo un maksimālo skaitu (kas ne vienmēr ir vienādi). Turklāt parasti lietojumprogramma prasa, lai šie datu argumenti komandrindā būtu pēdējie, taču tam ne vienmēr jābūt. Piemēram:

    java MyTool -a -b = logfile.inp data1 data2 data3 // Visi dati beigās 

    vai

    java MyTool -a data1 data2 -b = logfile.inp data3 // Var būt lietojumprogrammai pieņemams 
  • Sarežģītākas lietojumprogrammas var atbalstīt vairākas opciju kopas:

    java MyTool -a -b datafile.inp java MyTool -k [-verbose] foo bar duh java MyTool -check -verify logfile.out 
  • Visbeidzot, lietojumprogramma var izvēlēties ignorēt nezināmas opcijas vai uzskatīt šādas iespējas par kļūdām.

Tātad, izstrādājot veidu, kā ļaut lietotājiem izteikt visas šīs šķirnes, es nāca klajā ar šādu vispārīgo iespēju veidlapu, kas tiek izmantota kā pamats šim rakstam:

[[]] 

Šī forma jāapvieno ar daudzkārtības īpašību, kā aprakstīts iepriekš.

Ievērojot iepriekš aprakstītās iespējas vispārīgās formas ierobežojumus, Iespējas Šajā rakstā aprakstītā klase ir izstrādāta kā vispārējs risinājums visām komandrindas apstrādes vajadzībām, kas varētu būt Java lietojumprogrammai.

Palīgu klases

The Iespējas klase, kas ir šajā rakstā aprakstītā risinājuma galvenā klase, ir aprīkota ar divām palīgu klasēm:

  1. OptionData: Šajā klasē ir visa informācija par vienu konkrētu iespēju
  2. OptionSet: Šajā klasē ir vairākas iespējas. Iespējas pati var turēt jebkuru šādu kopu skaitu

Pirms aprakstīt sīkāku informāciju par šīm nodarbībām, jāņem vērā arī citi svarīgi Iespējas klase jāievieš.

Typesafe enums

Prefiksu, atdalītāju un īpašību daudzkārtība ir uztvērusi enums, šo funkciju pirmo reizi nodrošina Java 5:

public enum prefikss {DASH ('-'), SLASH ('/'); privāta char; privāts prefikss (char c) {this.c = c; } char getName () {return c; }} public enum Separator {COLON (':'), EQUALS ('='), BLANK (''), NONE ('D'); privāta char; privātais atdalītājs (char c) {this.c = c; } char getName () {return c; }} public enum Daudzkārtīgums {ONCE, ONCE_OR_MORE, ZERO_OR_ONE, ZERO_OR_MORE; } 

Enumu lietošanai ir dažas priekšrocības: paaugstināta tipa drošība un stingra, bez piepūles kontrolējama pieļaujamo vērtību kopa. Enumus var ērti izmantot arī ar ģenerētām kolekcijām.

Ņemiet vērā, ka Priedēklis un Atdalītājs enumiem ir savi konstruktori, ļaujot definēt faktisko raksturs kas pārstāv šo uzskaites gadījumu (pret nosaukums lieto, lai atsauktos uz konkrēto uzskaites gadījumu). Šīs rakstzīmes var iegūt, izmantojot šos enums ' getName () metodes, un rakstzīmes tiek izmantotas java.util.regex paketes raksta sintakse. Šo pakotni izmanto, lai veiktu dažas sintakses pārbaudes Iespējas klase, kuras detaļas sekos.

The Daudzveidība enum šobrīd atbalsta četras dažādas vērtības:

  1. VIENREIZ: Opcijai ir jānotiek tieši vienu reizi
  2. ONCE_OR_MORE: Opcijai ir jānotiek vismaz vienu reizi
  3. ZERO_OR_ONCE: Iespējas var būt vai nu nav, vai arī tā ir pieejama tieši vienu reizi
  4. ZERO_OR_MORE: Opcija var nebūt vai arī tā var būt redzama tik reižu, cik reižu

Ja rodas vajadzība, var viegli pievienot vairāk definīciju.

OptionData klase

The OptionData klase būtībā ir datu konteiners: pirmkārt, datiem, kas apraksta pašu opciju, un, otrkārt, faktiskajiem datiem, kas atrodami šīs opcijas komandrindā. Šis dizains jau ir atspoguļots konstruktorā:

OptionData (Opcijas. Prefiksa prefikss, virknes atslēga, Būla informācija, Opcijas. Atdalītāja atdalītājs, Būla vērtība, Opcijas. Daudzkārtības daudzkārtība) 

Atslēga tiek izmantota kā šīs opcijas unikālais identifikators. Ņemiet vērā, ka šie argumenti tieši atspoguļo iepriekš aprakstītos secinājumus: pilnā opcijas aprakstā jābūt vismaz prefiksam, atslēgai un daudzveidībai. Opcijām, kurās ņemta vērtība, ir atdalītājs, un tās var pieņemt detalizētu informāciju. Ņemiet vērā arī to, ka šim konstruktoram ir piekļuve pakotnei, tāpēc lietojumprogrammas to nevar tieši izmantot. Klase OptionSet's addOption () metode pievieno opcijas. Šim dizaina principam ir tā priekšrocība, ka mēs daudz labāk kontrolējam faktiskās iespējamās argumentu kombinācijas, kas tiek izmantotas, lai izveidotu OptionData gadījumi. Piemēram, ja šis konstruktors būtu publisks, jūs varētu izveidot instanci ar detalizētu iestatījumu uz taisnība un vērtība ir iestatīta uz nepatiesa, kas, protams, ir absurds. Tā vietā, lai man būtu sarežģītas pārbaudes pašā konstruktorā, es nolēmu nodrošināt kontrolētu komplektu addOption () metodes.

Konstruktors arī izveido instanci java.util.regex.Pattern, kas tiek izmantots šīs opcijas modeļu saskaņošanas procesā. Viens piemērs būtu tādas opcijas paraugs, kurā tiek ņemta vērtība, bez detaļām un atdalītājs bez tukša:

modelis = java.util.regex.Pattern.compile (prefikss.getName () + atslēga + separator.getName () + "(. +) $"); 

The OptionData klasē, kā jau minēts, glabājas arī Iespējas klasē. Tas nodrošina šādas publiskas metodes, lai piekļūtu šiem rezultātiem:

int getResultCount () virkne getResultValue (int indekss) virkne getResultDetail (int indekss) 

Pirmā metode, getResultCount (), atgriež opciju atrašanas reižu skaitu. Šis metodes dizains ir tieši saistīts ar opcijai noteikto daudzveidību. Opcijām, kurām ir vērtība, šo vērtību var iegūt, izmantojot getResultValue (int indekss) metodi, kur indekss var svārstīties starp 0 un getResultCount () - 1. Vērtību opcijām, kas arī pieņem detalizētu informāciju, tām var līdzīgi piekļūt, izmantojot getResultDetail (int indekss) metodi.

OptionSet klase

The OptionSet klase būtībā ir konteiners kopai OptionData gadījumi un arī komandrindā atrodamie datu argumenti.

Konstruktoram ir šāda forma:

OptionSet (Opcijas. Prefiksa prefikss, Opcijas. Daudzkārtības noklusējums. Daudzkārtība, String setName, int minData, int maxData) 

Arī šim konstruktoram ir piekļuve pakotnei. Opciju kopas var izveidot tikai caur Iespējas klase ir atšķirīga addSet () metodes. Šeit norādīto opciju noklusējuma daudzveidību var ignorēt, pievienojot opciju kopai. Šeit norādītais kopas nosaukums ir unikāls identifikators, ko izmanto, lai atsauktos uz kopu. minData un maxData ir minimālais un maksimālais pieļaujamo datu argumentu skaits šai kopai.

Vietnes API publiskā API OptionSet satur šādas metodes:

Vispārējās piekļuves metodes:

Virkne getSetName () int getMinData () int getMaxData () 

Opciju pievienošanas metodes:

OptionSet addOption (virknes atslēga) OptionSet addOption (virknes atslēga, daudzkārtība) OptionSet addOption (virknes atslēga, atdalītāja atdalītājs) OptionSet addOption (virknes atslēga, atdalītāja atdalītājs, daudzkārtības daudzkārtība) OptionSet addOption (virknes atslēga, Būla informācija, atdalītāja atdalītājs) (Virknes atslēga, būla informācija, atdalītāja atdalītājs, daudzkārtības daudzkārtība) 

Metodes, kā piekļūt pārbaudes rezultātu datiem:

java.util.ArrayList getOptionData () OptionData getOption (virknes atslēga) Boolean isSet (virknes atslēga) java.util.ArrayList getData () java.util.ArrayList getUnmatched () 

Ņemiet vērā, ka metožu pievienošana opcijām, kas prasa Atdalītājs arguments izveidot OptionData piemēram, pieņemot vērtību. The addOption () metodes atgriež pašu iestatīto gadījumu, kas ļauj piesaistīt ķēdi:

Opciju opcijas = new Opcijas (argumenti); options.addSet ("MySet"). addOption ("a"). addOption ("b"); 

Pēc pārbaužu veikšanas to rezultāti ir pieejami, izmantojot pārējās metodes. getOptionData () atgriež visu sarakstu OptionData gadījumi, kamēr getOption () ļauj tieši piekļūt noteiktai opcijai. isSet (virknes atslēga) ir ērtības metode, kas pārbauda, ​​vai komandrindā opcijas tika atrastas vismaz vienu reizi. getData () nodrošina piekļuvi atrastajiem datu argumentiem, savukārt getUnmatched () uzskaita visas komandrindā atrastās opcijas, kurām nav atbilstības OptionData gadījumi tika atrasti.

Opciju klase

Iespējas ir galvenā klase, ar kuru lietojumprogrammas mijiedarbosies. Tas nodrošina vairākus konstruktorus, kuri visi ņem komandrindas argumentu virknes masīvu, kas galvenais () metode kā pirmo argumentu nodrošina:

Opcijas (String args []) Opcijas (String args [], int dati) Opcijas (String args [], int defMinData, int defMaxData) Opcijas (String args [], Multiplicity defaultMultiplicity) Opcijas (String args [], Multiplicity defaultMultiplicity, int dati) Opcijas (String args [], Multiplicity defaultMultiplicity, int defMinData, int defMaxData) Opcijas (String args [], Prefix prefix) Opcijas (String args [], Prefix prefix, int data) Opcijas (String args [], Prefix prefikss, int defMinData, int defMaxData) Opcijas (String args [], Prefix prefix, Multiplicity defaultMultiplicity) Opcijas (String args [], Prefix prefix, Multiplicity defaultMultiplicity, int data) Opcijas (String args [], Prefix prefix, Multiplicity defaultMultiplicity, int defMinData, int defMaxData) 

Pirmais konstruktors šajā sarakstā ir vienkāršākais, izmantojot visas noklusējuma vērtības, bet pēdējais ir visizplatītākais.

1. tabula. Opciju () konstruktoru argumenti un to nozīme

Vērtība Apraksts Noklusējums
priedēklisŠis konstruktora arguments ir vienīgā vieta, kur var norādīt prefiksu. Šī vērtība tiek nodota jebkurai opciju kopai un jebkurai opcijai, kas izveidota pēc tam. Šīs pieejas ideja ir tāda, ka noteiktā lietojumprogrammā maz ticams, ka būs jāizmanto dažādi prefiksi.Prefikss. DASH
noklusējumsDaudzkārtībaŠis noklusējuma daudzveidība tiek nodota katrai opciju kopai un tiek izmantota kā noklusējums opcijām, kas pievienotas kopai, nenorādot daudzkārtību. Protams, šo daudzveidību var ignorēt attiecībā uz katru pievienoto opciju.Daudzveidība. VIENREIZ
defMinDatadefMinData ir noklusējuma minimālais atbalstīto datu argumentu skaits, kas nodots katrai opciju kopai, taču, protams, to var ignorēt, pievienojot kopu.0
defMaxDatadefMaxData ir noklusējuma maksimālais atbalstīto datu argumentu skaits, kas nodots katrai opciju kopai, taču, protams, to var ignorēt, pievienojot kopu.0
$config[zx-auto] not found$config[zx-overlay] not found