Après le java IO, revue de NIO! !!
En termes simples, il s'agit d'une amélioration par rapport aux E / S existantes.
https://docs.oracle.com/javase/jp/8/docs/api/java/io/InputStream.html#read-- "Cette method est bloquée jusqu'à ce que les données d'entrée puissent être lues, que la fin du flux soit détectée ou qu'une exception soit déclenchée."
Inefficace Puisque l'unité de traitement est byte, char, elle n'est pas efficace. Même si vous utilisez un flux de niveau élevé (tel que PrintStream), l'unité de traitement de base ne change pas.
Buffer Buffer est une classe abstraite, et il existe des sous-classes correspondant à des types de base autres que booléens.
Nom de l'élément | La description |
---|---|
capacity | Représente la taille du tampon |
limit | Tampon__Le premier INDEX qui ne peut pas être IO__ |
position | Tampon__Le premier INDEX qui peut être IO__ |
mark | La position que la position renvoie lorsque vous marquez et réinitialisez dans le tampon |
Les quatre facteurs ci-dessus satisfont ce qui suit 0 <= mark <= position <= limit <= capacity
Méthode | La description | Implémentation de CharBuffer |
---|---|---|
Buffer flip() | Préparez la sortie | limit = position positon = 0 mark = -1 |
int capacity() | Retour de capacité tampon | return capacity |
int limit() | Retour de limite de tampon | return limit |
int position() | Position du tampon retournée | return position |
int remaining() | Nombre d'éléments entre la position et la limite | return limit - position |
boolean hasRemaining() | Y a-t-il un élément entre la position et la limite | return position < limit |
Buffer position(int newPostion) | définir la position | Abréviation |
Buffer mark() | Marquer à la position actuelle | mark = position return this |
Buffer reset() | Position de retour pour marquer | int m = mark if (m < 0) throw new InvalidMarkException() position = m return this |
Buffer rewind() | Remettre la position en haut du tampon et annuler la marque | position = 0 mark = -1 return this |
Buffer clear() | Buffer Retour à l'état initial | position = 0 limit = capacity mark = -1 return this |
return toString (position (), limit ());
Méthode de sortie
private static void showProperty(CharBuffer buffer) {
System.out.println("capacity : " + buffer.capacity());
System.out.println("limit : " + buffer.limit());
System.out.println("position : " + buffer.position());
System.out.println("toString() : " + buffer.toString());
}
produire
CharBuffer buffer = CharBuffer.allocate(8);
System.out.println("-----Après génération-----");
showProperty(buffer);
production
----- Après la génération -----
capacity : 8
limit : 8
position : 0
toString() :
![Buffer-allocate.png](https://qiita-image-store.s3.amazonaws.com/0/104977/2497625d-f231-645a-d64d-19076d0ed910.png)
1.La fin du tampon est 8
2.Position de départ IO(position)vaut 0
3. toString()Est la position~Puisqu'il s'agit d'une limite, 8 nuls
#### **`put()`**
```java
buffer.put('a');
buffer.put('b');
buffer.put('c');
System.out.println ("----- Après avoir mis -----");
showProperty(buffer);
----- Après avoir mis -----
capacity : 8
limit : 8
position : 3
toString() :
flip()
buffer.flip();
System.out.println ("----- après le retournement -----");
showProperty(buffer);
----- Après retournement -----
capacity : 8
limit : 3
position : 0
toString() : abc
1.Premier INDEX qui ne peut pas être IO(limit)Est 3
2.Le premier INDEX qui peut être IO(position)La position de départ est 0
3. toString()Est la position~Parce que c'est une limiteabc
get()
buffer.get();
buffer.get();
System.out.println("-----get-----");
showProperty(buffer);
----- Après avoir -----
capacity : 8
limit : 3
position : 2
toString() : c
c
Pointer versc
clear()
buffer.clear();
System.out.println ("----- après effacement -----");
showProperty(buffer);
System.out.println("get(2) : " + buffer.get(2));
----- Après effacement -----
capacity : 8
limit : 8
position : 0
toString() : abc
get(2) : c
1.Puisqu'il revient à la position initiale, la position=0, limit,capacity=8
2.Non montré ici, mais marquez=-1
3. clear()Il suffit de retourner la position__Parce qu'il ne vide pas le tampon__、
clear()Obtenez même après(2)alorsc
が取得alorsきる
###prime ByterBuffer a allocateDirect()Il existe une méthode pour obtenir une instance avec. L'efficacité IO est élevée, mais le coût de production est élevé, il n'est donc pas adapté à une utilisation jetable.
Contact direct(Disque dur, réseau, etc.)C'est un tuyau qui se connecte à, et tous les IO__Grâce au tampon__Faire.
Méthode IO | La description |
---|---|
Channel#map | Mettez la plage de positions de début et de fin dans Buffer Lire la position(Channel.position)Ne pas enregistrer |
Channel#read | Mettre dans le tampon à partir du canal Enregistrer la position de lecture |
Channel#write | Mettre dans le canal à partir du tampon Enregistrez la position d'écriture |
###Implémentation partielle de Channel
channel-in.txt(UTF-8)
ab12
Ai
ab12 = 4byte Ai= 9byte \r\n = 2byte
map(),write()
try (
FileChannel channelIn = new FileInputStream(f).getChannel();
FileChannel channelOut = new FileOutputStream("./NIO/channel-out.txt").getChannel()) {
// map()
MappedByteBuffer mappedByteBuffer = channelIn.map(
FileChannel.MapMode.READ_ONLY, 0, f.length()
);
System.out.println("----channel#map----");
System.out.println("buffer capacity : " + mappedByteBuffer.capacity());
System.out.println("buffer limit : " + mappedByteBuffer.limit());
System.out.println("buffer position : " + mappedByteBuffer.position());
System.out.println("channel position : " + channelIn.position());
// write
channelOut.write(mappedByteBuffer);
System.out.println("----channel#write----");
System.out.println("buffer capacity : " + mappedByteBuffer.capacity());
System.out.println("buffer limit : " + mappedByteBuffer.limit());
System.out.println("buffer position : " + mappedByteBuffer.position());
System.out.println("channel position : " + channelOut.position());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
----channel#map----
buffer capacity : 15
buffer limit : 15
buffer position : 0
channel position : 0
----channel#write----
buffer capacity : 15
buffer limit : 15
buffer position : 15
channel position : 15
*traitement de la carte
* getChannel()
->Instanciation FileChannel
* 0, f.length()
-> 0~Obtenez 15 octets
* buffer position : 0
-> flip()Terminé
* channel position
-?Ne pas maintenir la position de lecture dans le fichier
out.write
-> position ~Limite d'écriturebuffer position : 15
->La position a été déplacée par le montant inscritchannel position : 15
->Index des fichiers la prochaine fois= 15(16e octet)Écrire à partir deFile f = new File("./NIO/channel-in.txt");
try (
FileChannel inChannel = new FileInputStream(f).getChannel()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
int hasRead = 0;
System.out.println ("---- channel # read 1st ----");
hasRead = inChannel.read(byteBuffer);
System.out.println("buffer capacity : " + byteBuffer.capacity());
System.out.println("buffer limit : " + byteBuffer.limit());
System.out.println("buffer position : " + byteBuffer.position());
System.out.println("channel position : " + inChannel.position());
System.out.println("hasRead : " + hasRead);
byteBuffer.clear();
System.out.println ("---- channel # read 2nd ----");
hasRead = inChannel.read(byteBuffer);
System.out.println("buffer capacity : " + byteBuffer.capacity());
System.out.println("buffer limit : " + byteBuffer.limit());
System.out.println("buffer position : " + byteBuffer.position());
System.out.println("channel position : " + inChannel.position());
System.out.println("hasRead : " + hasRead);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
---- numéro de canal lu 1ère fois ----
buffer capacity : 8
buffer limit : 8
buffer position : 8
channel position : 8
hasRead : 8
---- numéro de canal lu 2ème fois ----
buffer capacity : 8
buffer limit : 8
buffer position : 7
channel position : 15
hasRead : 7
*lire 1ère fois
* buffer position : 8
->8 octets lus
* channel position : 8
->Vient ensuite l'index des fichiers= 8(9e octet)Lire de
*lire la 2ème fois
* buffer position : 7
->7 octets lus
* channel position : 15
->Vient ensuite l'index des fichiers= 15(9e octet)Lire de
java utilise Unicode par défaut, mais des caractères déformés peuvent se produire lors de la lecture d'autres codes de caractères. Charset est fourni pour la conversion d'octet et de caractère.
Méthode IO | La description |
---|---|
CharBuffer Charset#decode(ByteBuffer buf) | ByteBuffer to CharBuffer |
ByteBuffer Charset#encode(CharBuffer buf) | CharBuffer to ByteBuffer |
ByteBuffer Charset#encode(String str) | String to ByteBuffer |
###Obtenir le jeu de caractères pris en charge par java
Charset.availableCharsets()
// Liste des jeux de caractères
Charset.availableCharsets().entrySet().forEach(System.out::println);
// defalut
System.out.println("default charset : " + Charset.defaultCharset()); // UTF-8
partie
・ ・ ・ Abréviation
Shift_JIS=Shift_JIS
UTF-16=UTF-16
UTF-32=UTF-32
UTF-8=UTF-8
・ ・ ・ Abréviation
Lire le fichier SJIS
File f = new File("./NIO/file-sjis-in.txt");
try (
FileChannel inChannel = new FileInputStream(f).getChannel()) {
// FileChannel to ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
inChannel.read(byteBuffer);
byteBuffer.flip();
// Shift_JIS
Charset sjis = Charset.forName("Shift_JIS");
// decode buff with SJIS
CharBuffer charBuffer = sjis.decode(byteBuffer);
System.out.println("str : " + charBuffer.toString());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
String(unicode)Est écrit en SJIS
try (
FileChannel outChannel = new FileOutputStream("./NIO/file-sjis-out.txt").getChannel()) {
// unicode
Chaîne str = "123 Ai" + System.lineSeparator () + "SHIFT-JIS";
// Shift_JIS
Charset sjis = Charset.forName("Shift_JIS");
// encode buff with SJIS
ByteBuffer byteBuffer = sjis.encode(str);
// write to file
outChannel.write(byteBuffer);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
Ou
C'est aussi dans String! !!
new String(byte[] xx, "Shift_JIS");
###Un point peu clair utf-8(1byte ~ 6byte)Lorsque le nombre d'octets diffère selon le caractère, tel que Que dois-je faire avec la taille du tampon? ?? ??
UTF-8 fiches
ab ai
ab = 2byte Ai= 3byte + 3byte
ByteBuffer byteBuffer = ByteBuffer.allocate(6)
Si défini sur
ab ah
+ 1er octet
Va dans le tampon et décodeab ah�
devenir.
Que dois-je faire dans ce cas? ?? ??
2.Déterminez les caractères déformés, placez-les au début du tampon, ajustez la position et lisez. ⇒ map()Ne bloque pas la lecture et la position du fichier! ~~Dois-je spécifier une taille qui ne déforme pas? ??~~
La solution est ci-dessous.
contrôle | La description |
---|---|
onMalformedInput | Erreur de saisie illégale |
onUnmappableCharacter | Erreur de caractère non mappé |
Type | La description |
---|---|
CodingErrorAction.IGNORE | Ignorer les caractères d'erreur |
CodingErrorAction.REPLACE | Remplacement du caractère d'erreur |
CodingErrorAction.REPORT | Rapport d'erreur |
Échantillon IGNORER
File f = new File("./a/file-utf8-in.txt");
try (
FileChannel inChannel = new FileInputStream(f).getChannel()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
while (inChannel.read(byteBuffer) > -1) {
// Préparation IO
byteBuffer.flip();
Charset utf8 = Charset.forName("UTF-8");
CharsetDecoder decoder = utf8.newDecoder();
CharBuffer charBuffer2 = decoder
.onMalformedInput(CodingErrorAction.IGNORE)
.decode(byteBuffer);
System.out.print(charBuffer2.toString());
byteBuffer.clear();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
production
ab ah
je
A été ignoré
IGNORE
File f = new File("./a/file-utf8-in.txt");
try (
FileChannel inChannel = new FileInputStream(f).getChannel()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
while (inChannel.read(byteBuffer) > -1) {
// Préparation IO
byteBuffer.flip();
Charset utf8 = Charset.forName("UTF-8");
CharsetDecoder decoder = utf8.newDecoder();
CharBuffer charBuffer2 = decoder
.onMalformedInput (CodingErrorAction.REPLACE) .replaceWith ("O")
.decode(byteBuffer);
System.out.print(charBuffer2.toString());
byteBuffer.clear();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
production
ab Aoo
je
1er octet ⇒
je
2e octet ⇒
je
3e octet ⇒
IGNORE,REPLACE détruit les données d'origine !!
REPORT
File f = new File("./a/file-utf8-in.txt");
try (
FileChannel inChannel = new FileInputStream(f).getChannel()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(6);
while (inChannel.read(byteBuffer) > -1) {
byteBuffer.flip();
Charset utf8 = Charset.forName("UTF-8");
CharsetDecoder decoder = utf8.newDecoder();
try {
CharBuffer charBuffer = decoder
.onMalformedInput(CodingErrorAction.REPORT)
.decode(byteBuffer);
// Production
System.out.print(charBuffer.toString());
byteBuffer.clear();
} catch (MalformedInputException ex) {
// Position d'occurrence d'erreur et position finale
int errorIndexStart = byteBuffer.position();
int errorIndexEnd = byteBuffer.limit();
// Sortie en position normale
byteBuffer.flip();
CharBuffer charBuffer = decoder
.decode(byteBuffer);
System.out.print(charBuffer.toString());
// Déplace le début à la fin de la position d'erreur au début du tampon
byteBuffer.clear();
for (int i = errorIndexStart; i < errorIndexEnd; i++) {
byteBuffer.put(byteBuffer.get(i));
}
}
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
ab ai
1.Lorsqu'une erreur se produit, première sortie en position normale. 2.Passer de la position d'occurrence d'erreur à la fin du tampon 3.La lecture suivante est après la longueur de l'erreur, pas à partir de 0 4. utf-8 est de 1 à 6 octets, donc allouez au moins(6)As-tu besoin?
Est-ce vraiment le meilleur? ??
Représente un verrou sur un fichier
Méthode de verrouillage FileChannel | La description |
---|---|
FileChannel#lock() | lock(0L, Long.MAX_VALUE, false) |
FileChannel#lock(long position, long size, boolean shared) | Plage de verrouillage, verrouillage partagé, verrouillage exclusif peut être spécifié |
FileChannel#tryLock() | tryLock(0L, Long.MAX_VALUE, false) |
FileChannel#tryLock(long position, long size, boolean shared) | Plage de verrouillage, verrouillage partagé, verrouillage exclusif peut être spécifié |
lock()Bloque les filetages jusqu'à l'acquisition du verrouillage. tryLock renvoie null si le verrou ne peut pas être acquis.
échantillon de verrouillage
try (FileChannel fileChannel = new FileOutputStream("file-lock-out.txt").getChannel();) {
FileLock lock = fileChannel.lock();
System.out.println ("verrou a été obtenu");
System.out.println ("Gardez le verrou pendant 60 secondes");
Thread.sleep(60 * 1000);
lock.release();
} catch (IOException | InterruptedException ex) {
System.out.println("1" + ex.getMessage());
}
Lorsque ce qui précède est exécuté deux fois avec différents jvm
sortie de jvm1
J'ai pu obtenir la serrure
Gardez le verrou pendant 60 secondes
Il n'y a pas de sortie car la sortie de jvm2 attend.
tryLock()échantillon
try (FileChannel fileChannel = new FileOutputStream("file-lock-out.txt").getChannel();) {
FileLock lock = fileChannel.tryLock();
if (lock != null) {
System.out.println ("tryLock a été acquis");
Thread.sleep(60 * 1000);
lock.release();
} else {
System.out.println("lock is null");
}
} catch (IOException | InterruptedException ex) {
System.out.println(ex.getMessage());
}
sortie jvm1
J'ai pu obtenir tryLock
sortie jvm2
lock is null
###Autre 1.Puisque le verrou appartient à jvm, vous ne pouvez pas verrouiller le même fichier avec le même jvm. 2.Sur certaines plates-formes, le verrou est libéré lorsque le FileChannel est fermé. Il n'est donc pas bon d'ouvrir plusieurs FileChannels pour les fichiers verrouillés. 3.Sur certaines plates-formes, les verrous de fichiers sont recommandés et non obligatoires. ⇒ Vous pouvez lire et écrire sans verrou.
#Vient ensuite NIO.2 https://qiita.com/liguofeng29/items/3d0ba350a1547630727b
Recommended Posts