1s 8 binarnih podataka u datoteku. Proširivanje funkcionalnosti rada sa binarnim podacima. Čitanje binarnih podataka

Gotovo sve informacije mogu se pohraniti u skladište vrijednosti, npr.

... slike (fotografije):

CurrentImage.Object = SprFabric.Link; CurrentImage.DataType = Enumerations.Types of Additional Information of Objects.Image; Skladište = NewValueStorage(NovaSlika, NewDataCompression()); CurrentImage.Storage = Storage.Get();

// na ovom mjestu prikazuje sve... Form Elements.PictureField1.Picture = Storage.Get(); CurrentImage.Write();

...proračunski dokument:

TabDoc=Novi tablični dokument;

TabDoc.Output(FormElements.TabularDocumentField1);

Storage=NewValueStorage(TabDoc);

Write();<>Kraj procedure

Procedura RestoreFromStoragePress(Element)

TabDoc=Storage.Get();

Ako TabDoc

Undefined ThenFormElements.TabularDocumentField1.Output(TabDoc);

endIf;

Kraj procedure

... proizvoljni fajlovi (binarni podaci):

XZ = NewValueStorage(NewBinaryData(file));

TabDoc.Output(FormElements.TabularDocumentField1);

Osam podržava kompresiju podataka smještenih u pohranu:

XZ = NewValueStorage(NewBinaryData(file),NewDataCompression(9));

Procedura RestoreFromStoragePress(Element)

... eksterna obrada i izvještavanje:

Procedura LoadProcessingIntoStorage(PropsStorageType)

Stopa kompresije = NewDataCompression(9); //9 maksimalnih PropsStorageType = New StorageValues(New BinaryData("c:\reports\report.epf", Omjer kompresije));<>Procedura StartProcessingFromStorage(PropsStorageType)

TemporaryFileName = TemporaryFileDirectory()+"report.epf";

BinarniData = PropsStorageType.Get();

BinaryData.Write(TemporaryFileName);

ExternalProcessing = ExternalProcessing.Create(TemporaryFileName);

ExternalProcessing.GetForm().Open();

Da obrišete polje tipa Pohrana vrijednosti, morate mu dodijeliti Nedefinirano:

PropsStorage = Nedefinisano;

Rad sa datotekama i slikama na ugrađenom jeziku 1C:Enterprise 8

Svrha

Upravljana aplikacija implementira novi mehanizam za rad sa datotekama. Omogućava razmjenu datoteka između baze podataka i klijentske aplikacije. Posebnost ovog mehanizma je u tome što je dizajniran za upotrebu u tankom klijentu i Web klijentu i dizajniran je uzimajući u obzir ograničenja rada sa datotekama koja nameću web pretraživači.

Mehanizam je skup metoda koji se mogu koristiti za postavljanje podataka pohranjenih lokalno na korisnikovom računaru u privremeno skladište baze podataka, prenošenje ovih informacija iz privremene memorije u bazu podataka i njihovo vraćanje na računar korisnika. Najčešći aplikativni problemi koji se rješavaju ovim mehanizmom su pohranjivanje pratećih informacija, na primjer, slike robe, dokumenta vezana za ugovore itd.

Obim metode

Privremeno skladište

Privremena pohrana je specijalizirana oblast informacijske baze u koju se mogu smjestiti binarni podaci. Glavna svrha je privremeno skladištenje informacija tokom interakcije klijent-server prije nego što se prenesu u bazu podataka.

Potreba za privremenim skladištenjem nastaje jer operativni model web pretraživača zahtijeva da se datoteka koju odabere korisnik prenese direktno na server bez mogućnosti pohranjivanja na klijentu. Kada se datoteka prenese, ona se stavlja u privremenu memoriju i može se koristiti prilikom pisanja objekta u bazu podataka.

Najtipičniji zadatak aplikacije koji se rješava privremenim skladištenjem je omogućavanje pristupa datotekama ili slikama prije nego što se objekt zabilježi u informacijskoj bazi, na primjer, u obliku elementa.

Datoteka ili binarni podaci smješteni u memoriju identificiraju se jedinstvenom adresom, koja se kasnije može koristiti u operacijama pisanja, čitanja ili brisanja. Ova adresa je data metodama za pisanje datoteke u privremenu memoriju. Zasebna metoda u ugrađenom jeziku omogućava vam da odredite da li je proslijeđena adresa adresa koja upućuje na podatke u privremenoj memoriji.

Baza informacija

Mehanizam vam omogućava pristup binarnim podacima pohranjenim u atributima tipa Value Storage.

Kao iu slučaju privremenog skladištenja, pristup informacijama je moguć preko posebne adrese. Možete ga dobiti putem posebne metode prosljeđivanjem veze do objekta ili ključa za unos informacija u registar i imena atributa. U slučaju tabelarnog dijela, dodatno je potrebno prenijeti indeks reda tabelarnog dijela.

Metode za rad sa datotekama imaju ograničenja u radu sa detaljima baze podataka. Za njih, za razliku od privremenog skladištenja, dostupno je samo čitanje informacija, ali ne i njihovo pisanje ili brisanje.

Opis metoda za rad sa datotekama

Pohranjivanje podataka u privremenu memoriju

Najtipičniji scenario za korištenje ovog mehanizma uključuje početno stavljanje korisničkih podataka u privremenu memoriju. Za to postoje dvije metode: PlaceFile() i PlaceFileInTemporaryStorage().

Prva metoda, PlaceFile(), postavlja datoteku iz lokalnog sistema datoteka u privremenu memoriju. Metoda može prihvatiti ciljnu adresu u memoriji. Ako nije definiran ili je prazan niz, tada će se kreirati nova datoteka i metoda će vratiti svoju adresu kroz odgovarajući parametar.

Ako je parametar koji određuje interaktivni način rada True, tada će metoda prikazati standardni dijaloški okvir za odabir datoteke u kojem možete odabrati datoteku koju želite smjestiti u pohranu. U ovom slučaju, metoda će također vratiti adresu odabrane datoteke.

Kao rezultat, metoda vraća False ako je korisnik interaktivno odbio izvršiti operaciju u dijalogu za odabir datoteke. Metoda je dostupna samo na klijentu.

Druga metoda, PlaceFileInTemporaryStorage(), je slična prethodnoj, samo što je dostupna na serveru, a podaci koji se upisuju u privremenu memoriju nisu predstavljeni kao putanja u sistemu datoteka, već kao varijabla tipa BinarniData. Isto tako, ako nije navedena ciljna adresa, kreira se nova datoteka u memoriji. Njegova adresa se vraća kao rezultat funkcije.

Preuzimanje datoteke iz privremene memorije

Prilikom pisanja objekta u infobazu, možda ćete morati izdvojiti podatke iz privremene memorije i smjestiti ih, na primjer, u atribut. Za ovo postoji odgovarajuća serverska metoda - GetFileFromTemporaryStorage(). Ova metoda preuzima podatke iz privremene memorije i vraća ih kao rezultat. Da biste to učinili, morate navesti adresu u privremenoj memoriji. Ovu adresu vraćaju gore opisane metode PlaceFile() i PlaceFileInTemporaryStorage() ako se uspješno izvrše.

Brisanje fajla iz privremene memorije

Nakon što su podaci sačuvani u detaljima, datoteka u privremenoj memoriji može se izbrisati. U tu svrhu postoji metoda DeleteFileFromTemporaryStorage(), koja briše datoteku iz privremene memorije. Metoda uzima kao parametar adresu datoteke u privremenoj memoriji. Dostupno na serveru.

Provjera adrese za privremeno skladištenje

Adresa datoteke može ukazivati ​​i na privremenu memoriju i detalje u bazi podataka. Za provjeru njegovog tipa postoji metoda This isTemporaryStorageAddress().

Provjerava da li je proslijeđena adresa adresa koja upućuje na trgovinu. Vraća True ako adresa ukazuje na privremenu memoriju. Metoda je dostupna na serveru.

Primanje adrese rekvizita

Nakon što su podaci stavljeni u detalje u bazi podataka, možda ćete morati da im pristupite pomoću metoda datoteka.

Ali prije primanja podataka, na primjer od imovine, morate dobiti adresu ove nekretnine. U tu svrhu postoji metoda GetFileAddressInInformationBase().

Njegova svrha je da vrati adresu datoteke u infobazu prema originalnim parametrima. Da biste to učinili, trebate proslijediti ključ objekta (ovo može biti ili veza do objekta ili ključ za unos informacija u registar) i naziv atributa. Ako trebate dobiti adresu datoteke pohranjene u atributu tabelarnog dijela, prije imena atributa u parametru koji specificira ime atributa, potrebno je dodati naziv tabelarnog dijela i tačku “.”. Metoda je dostupna i na klijentu i na serveru.

Preuzimanje fajla iz infobaze

GetFile() metoda prima datoteku iz baze podataka i sprema je u korisnički lokalni sistem datoteka. Prvi parametar specificira adresu datoteke u rekviziti ili privremenoj memoriji datoteka. Drugi parametar specificira odredišnu lokaciju rezultirajuće datoteke. U neinteraktivnom načinu rada, morate navesti putanju. U interaktivnom načinu rada, parametar je opcionalan.

Metoda se podrazumevano izvršava u interaktivnom režimu, odnosno poslednji parametar je True. To znači da se prikazuje dijaloški okvir u kojem možete odrediti radnju s primljenom datotekom: pokrenuti je ili spremiti na lokaciju koju odredi korisnik. Ako je interaktivni način aktivan i parametar putanje datoteke ciljnog diska nije specificiran, operacija otvaranja datoteke nije dostupna. Vraća logičku vrijednost. Netačno znači da je korisnik izabrao da otkaže operaciju u interaktivnom dijaloškom okviru za spremanje datoteke.

Primjer korištenja metoda datoteka

// Primanje datoteke s diska u interaktivnom načinu // i postavljanje u privremenu memoriju &Na klijentskoj proceduri SelectDiskFileAndWrite()

Varijabla SelectedName;

TabDoc.Output(FormElements.TabularDocumentField1);

VariableTemporaryStorageAddress;

Ako PutFile(TemporaryStorageAddress, SelectedName, True) onda Object.FileName = SelectedName;

TabDoc.Output(FormElements.TabularDocumentField1);

PlaceObjectFile(TemporaryStorageAddress);

endIf;

Procedura RestoreFromStoragePress(Element)

// Kopiranje datoteke iz privremene memorije u // atribut direktorija, snimanje objekta, brisanje datoteke iz privremene // memorije &Na serveru Procedura Postavite objektnu datoteku (adresa privremene pohrane)

Element direktorija = Form AttributesValue("Object");

BinaryData = GetFileFromTemporaryStorage(TemporaryStorageAddress);

Element direktorija. Podaci datoteke = NewValueStorage(BinaryData); FilePathOnDisk = Nova datoteka(DirectoryItem.FileName);

Ime stavke direktorija = FilePathOnDisk.Name;

Element direktorija.Write();

Modificirano = Netačno;

DeleteFileFromTemporaryStorage(TemporaryStorageAddress);

ValueVFormAttributes(Element direktorija, "Objekat");

// Čitanje datoteke iz rekvizita i spremanje // na lokalni disk u interaktivnom načinu &Na klijentskoj proceduri ReadFileAndSaveToDisk()

Kada dokument ima atribut tipa Skladište vrijednosti u tabličnom dijelu, to usporava otvaranje obrasca dokumenta ako ovaj atribut sadrži velike podatke.

Pretpostavljeni razlog:

Možda se prilikom otvaranja obrasca klijentu ne šalje veza do podataka koji se nalaze u Value Storeu, već sami podaci.

Rješenje

  • U svojstvima atributa tabele obrasca nalazi se zastavica "Uvek koristi". Ako je postavljeno, sadržaj polja se uvijek prenosi između servera i klijenta - na primjer, prilikom otvaranja obrasca. Ova zastavica mora biti onemogućena, ali to se mora uzeti u obzir u kodu, jer po defaultu neće biti vrijednosti za ovo polje na klijentu. Primjer se može naći u 1C: Arhiva.

Još je bolje koristiti privremeno skladište za prijenos datoteka između klijenta i servera.

Implementirano u verziji 8.3.10.2168.

Postepeno povećavamo funkcionalnost za rad sa binarnim podacima. Postoji nekoliko razloga za to. Prvo, nismo realizovali sve što smo planirali. I drugo, u procesu razgovora o novim mogućnostima, od vas smo dobili niz želja koje smo takođe odlučili da realizujemo.

Nove funkcije za pretvaranje binarnih podataka u različite formate

U globalnom kontekstu, dodali smo veliki broj novih funkcija za pretvaranje binarnih podataka. Tako, na primjer, možete izvršiti naprijed i nazad konverziju binarnih podataka u običan string, format string Base64 i format string BinHex. Osim toga, možete i same binarne podatke pretvoriti u formate Base64, BinHex i nazad.

Slične konverzije su podržane za tip BufferBinaryData. Osim toga, možete pretvoriti bafer binarnih podataka u binarne podatke i obrnuto.

Osim toga, dvije nove funkcije vam omogućavaju da podijelite binarne podatke na nekoliko dijelova, i obrnuto, da kombinirate nekoliko objekata tipa BinarniData u jednom. U ovom slučaju, novi objekt će sadržavati podatke svih dijelova redoslijedom koji odredite.

Ove funkcije su po konceptu slične dijeljenju i spajanju datoteka, ali u mnogim slučajevima su efikasnije. Zato što nema potrebe za prvo spremanje binarnih podataka u datoteku i zato što nema nepotrebnog kopiranja podataka prilikom razdvajanja.

Dodavanje mogućnosti rada sa streamovima objektima koji rade s datotekama

Budući da je korištenje binarnih podataka u velikoj mjeri povezano s operacijama datoteka, smatrali smo da je potpuno logično i prirodno dodati rad sa streamovima onim objektima koji trenutno čitaju i pišu datoteke na ovaj ili onaj način.

Kao rezultat, sada možete otvarati tokove za čitanje i pisanje kada koristite objekte kao što su:

  • ReadingText I WriteText;
  • ReadingFastInfoSet I EntryFastInfoSet;
  • ReadingHtml I PostHtml;
  • Čitanje JSON-a I JSON unos;
  • Čitanje XML-a I XML unos;
  • Čitanje Zip datoteke I Snimi zip datoteku.

Možete primiti tijelo kao stream kada radite sa HTTP-om:

  • HTTPRequest I HTTPResponse;
  • HTTPServiceRequest I HTTPServiceResponse.
  • TextDocument;
  • TabularDocument;
  • FormattedDocument;
  • GeographicalScheme;
  • GraphicScheme;
  • FTPConnection.

Pisanje u stream je sada dostupno kada radite sa tipovima Slika I ConvertToCanonicalXML. Osim toga, rad sa streamovima je sada podržan raznim metodama koje tipovi imaju XSL konverzija, Menadžer kriptografije, CertificateCryptography I HashingData.

Efikasno kopiranje čitanjem i pisanjem podataka

Binarni alati koje smo implementirali omogućili su kopiranje tokova. Ali na velikim količinama podataka ova operacija nije izvedena vrlo efikasno.

Dakle, tip ReadData implementirali smo novu metodu CopyB(). Ne samo da eliminiše ovaj problem, već i pojednostavljuje tekst, čineći ga razumljivijim.

Na primjer, ranije je bilo moguće primati binarne podatke iz jednog toka i pisati ih u drugi tok.

Sada nema potrebe za primanjem binarnih podataka, kopiranje se vrši u fazi čitanja podataka.

Dobra stvar je što možete kopirati ne samo u stream, već i na objekat WriteData. Ova opcija je zgodna kada, osim podataka iz izvornog toka, trebate upisati neke svoje podatke u izlazni tok.

Bitove logičke operacije na baferu binarnih podataka

Sada možete koristiti bitne logičke operacije kada radite sa binarnim baferima podataka. Kao rezultat ovih operacija, rezultat bitne kombinacije originalnih bajtova i bajtova u datom međuspremniku biće upisan u izvorni bafer prema pravilima odabrane logičke operacije. Realizovali smo sledeće operacije:

  • WriteBitBit();
  • WriteBitOr();
  • WriteBitExclusiveOr();
  • WriteBitIne();
  • Invert().

Dobar primjer upotrebe bitnih logičkih operacija je zadatak dekodiranja formata razmjene sa maloprodajnom opremom. Na primjer, format razmjene sa maloprodajnom opremom opisan je poljem od 1 bajta. Ovo polje sadrži skup karakteristika koje opisuju asortiman proizvoda:

  • Bitovi 0-2: poreska stopa;
  • Bit 3: 0 - komadna roba, 1 - težina robe;
  • Bit 4: 0 - dozvoli prodaju, 1 - zabrani prodaju;
  • Bit 5: 0 - omogućiti brojanje količine, 1 - onemogućiti brojanje količine;
  • Bit 6: 0 - pojedinačna prodaja je zabranjena, 1 - pojedinačna prodaja je dozvoljena;
  • Bit 7: Rezervisano.

Tada kod koji izdvaja ove informacije i predstavlja ih u obliku pogodnom za dalju obradu može izgledati ovako.

Dobijanje broja iz heksadecimalnih i binarnih literala

  • NumberFromHexString();
  • NumberFromBinaryString().

Binarni literali su korisni za definiranje maski kada se koriste u kombinaciji s bitwise operacijama. Na primjer, u prethodnom primjeru s analizom formata razmjene sa komercijalnom opremom, maske su specificirane pomoću decimalnih brojeva. Ovo nije baš zgodno, jer prilikom pisanja i čitanja koda morate stalno mentalno prevoditi decimalni broj u binarni sistem.

Mnogo je zgodnije koristiti binarne literale umjesto toga. Istovremeno, kod postaje jasniji i vjerovatnoća grešaka je značajno smanjena.

Heksadecimalni literali su zgodni za korištenje prilikom raščlanjivanja tehničkih formata: slike, zvuka, video formata.

Promjene u tehnologiji vanjskih NativeAPI komponenti

Ranije je postojao niz ograničenja prilikom prijenosa binarnih podataka između 1C:Enterprise i eksterne komponente. Na primjer, bilo je nemoguće prenijeti binarne podatke na vanjsku komponentu, a kada se radi u web klijentu, razmjena binarnih podataka je općenito bila nemoguća.

Sada uklanjamo sva ova ograničenja. Možete razmjenjivati ​​binarne podatke u oba smjera, pa čak i u web klijentu.

To ni na koji način neće utjecati na rad postojećih vanjskih komponenti. Oni će raditi kao i do sada. Ali u novokreiranim komponentama sada možete proslijediti objekte kao parametre BinarniData.

Tehnološka platforma 1C:Enterprise 8 omogućava vam da spremate proizvoljne datoteke u bazu podataka, da ih odatle preuzimate i koristite na različite načine. Pogledajmo ove operacije koristeći primjere.

Prije učitavanja datoteke u bazu podataka 1C, morate dobiti punu adresu datoteke na disku. Rad s dijalozima za odabir datoteka opisan je u .

Za pohranjivanje datoteka koristite atribut (ili registarski resurs) s tipom StorageValues.

Prijenos proizvoljne datoteke u bazu podataka 1C

Bilo koja datoteka može biti predstavljena kao binarni podatak i učitana u Value Storage.

Prilikom pretvaranja binarnih podataka u objekt StorageValues korišten dizajn nove StorageValues ​​(podaci, kompresija) sa dva parametra:

  1. Podaci— binarni podaci koji se moraju pohraniti u memoriju
  2. Kompresija— omjer kompresije algoritma deflacije. Cijeli broj u rasponu -1...9. -1 je zadani nivo kompresije. 0 - nema kompresije, 9 - maksimalna kompresija. Zadana vrijednost: -1. Parametar je opcioni, ako nije naveden, onda se kompresija ne koristi.

//Pretvorite datoteku u binarne podatke
Fajl = Novi binarni podaci (putanja) ;

//Kreirajte novi objekt za pohranu vrijednosti

DataStorage = NewValueStorage(File, NewDataCompression(9) ) ;

Spremanje proizvoljne datoteke iz 1C infobaze na disk

Da biste spremili datoteku iz 1C baze podataka na disk, morate odrediti stazu i naziv datoteke. Da biste to učinili, postoji dijalog za spremanje datoteke, rad s kojim je opisan u.

//Nabavite binarne podatke iz skladišta
//Skladištenje podataka - atribut objekta s tipom Value Storage

//Upis primljenih podataka na disk
//Varijabla Putanja sadrži punu adresu datoteke na disku
Podaci. Pisanje (putanja) ;

Pregledanje datoteke koja se nalazi u bazi podataka 1C

Da biste vidjeli datoteku sačuvanu u bazi podataka, morate imati instaliranu aplikaciju na vašem računaru koja otvara datoteku.

//Nabavite ime privremene datoteke sa potrebnom ekstenzijom
//U varijablu Extension morate staviti ekstenziju datoteke, na primjer "pdf"
Putanja = GetTemporaryFileName(Extension) ;

//Primanje podataka iz skladišta
//Skladištenje podataka - atribut objekta s tipom Value Storage
Podaci = Skladište podataka. Get() ;

//Upisivanje podataka u privremenu datoteku
Podaci. Pisanje (putanja) ;

//Pokušavam otvoriti datoteku u predviđenoj aplikaciji
//Ako aplikacija nije pronađena, pojavit će se sistemski dijalog "Otvori sa...".
LaunchApplication (putanja) ;

Binarni podaci u 1C namijenjeni su za pohranjivanje datoteka proizvoljnog formata. Uz njihovu pomoć možete:

  • Organizirati interakciju korištenjem binarnog protokola s različitim uređajima;
  • Čuvajte datoteke bilo kojeg formata kao atribute metapodataka;
  • Pretvorite tekstualne podatke u binarne (najčešće se koriste za slanje izvještaja);
  • Rad sa binarnim podacima u memoriji.

Šta sistem može da uradi

Prilikom rada sa binarnim podacima, Platforma 8.3 može izvršiti sljedeće radnje:

  1. Čitanje i pisanje binarnih podataka;
  2. Premještanje podataka sa klijenta na server i nazad koristeći privremenu memoriju;
  3. Inicijalizirati objekt tipa “Slika” koristeći binarne datoteke;
  4. Pročitajte ih sa World Wide Weba koristeći objekte “Privitak pošte”, “HTTP veza” itd.
  5. Koristite kriptografske alate za šifriranje i potpisivanje važnih priloga;
  6. Koristeći objekat “Data Hashing”, izračunajte hash funkciju.

Spremanje podataka u detalje

Na primjer, napravimo direktorij u probnoj konfiguraciji.

U stvari, korištenje istog direktorija za pohranjivanje informacija o nomenklaturi i binarnim slikama je malo pogrešno. Uz dovoljno velike količine podataka i teške, velike datoteke, može doći do neželjenih zastoja i „kočnica“ u radu sistema. Sa stanovišta sistema, bilo bi mnogo ispravnije organizovati poseban direktorijum „Slike“, link do kojeg bismo mogli postaviti kao tip rekvizita.


Važno je napomenuti da zbog činjenice da atributi tipa “ValueStorage” koji sadrže binarne podatke nisu dostupni u režimu upravljane aplikacije, njima se može pristupiti samo pomoću metode FormAttributesValue.


Polje poruke predstavlja binarni zapis podataka spremišta vrijednosti.

Čitanje podataka iz rekvizita

Kreirajmo obradu koja će datoteku pohranjenu u binarnoj formi u našoj konfiguraciji izvesti u tabelarni dokument (ovo je potrebno, na primjer, za štampanje logotipa kompanije).


U suštini, ovo je sav kod koji nam treba. Koristeći Get() operator, čitamo binarne podatke pohranjene u odgovarajućem atributu direktorija i prenosimo ih u objekt “Slika” koji će biti prikazan u gornjoj lijevoj ćeliji tabelarnog dokumenta obrasca (slika 9).

Fig.9

Konverzija podataka

Nije uobičajeno, ali se dešava da je pri radu sa nestandardnim razmjenama sa eksternim sistemima potrebno konvertirati podatke iz binarnog formata u Base64 format ili obrnuto.

U većini slučajeva, platforma automatski konvertuje podatke ako se to ne dogodi, morate koristiti globalne funkcije prevođenja:

  1. Base64String – konvertuje navedenu vrednost u niz odgovarajućeg kodiranja;
  2. Base64Value – vrši obrnutu konverziju.

Optimizacija gornjeg koda

Kod predstavljen na slici 4 svakako radi, ali uz jedno značajno upozorenje: ako je polje za potvrdu “Modality use mode” označeno u svojstvima konfiguracije (Slika 10). U suprotnom, njegovo korištenje će uzrokovati grešku.
Fig.10

Kako biste spriječili da se to dogodi, dok ste u modulu obrasca elementa direktorija, idite na meni Text->Refactoring->Deprecated synchronous calls->Convert module calls.

Nakon nekog vremena, sinhroni pozivi će se automatski pretvoriti u asinhrone, a kod će poprimiti oblik (slika 11)

Fig.11