NIO Bewertung von Java

Lesen Sie nach dem Java IO einen Bericht über NIO! !!

Was ist NIO?

Einfach ausgedrückt ist dies eine Verbesserung gegenüber vorhandenen E / A.

Schlechte Punkte bestehender E / A.

  1. https://docs.oracle.com/javase/jp/8/docs/api/java/io/InputStream.html#read-- "Diese Methode wird blockiert, bis die Eingabedaten gelesen werden können, das Ende des Streams erkannt wird oder eine Ausnahme ausgelöst wird."

  2. Ineffizient Da die Verarbeitungseinheit Byte, char ist, ist sie nicht effizient. Selbst wenn Sie einen Stream auf hoher Ebene verwenden (z. B. PrintStream), ändert sich die Basisverarbeitungseinheit nicht.

NIOs Kern-API

Buffer Buffer ist eine abstrakte Klasse, und es gibt Unterklassen, die anderen Grundtypen als Boolean entsprechen.

Wichtige Elemente im Puffer

Elementname Erläuterung
capacity Repräsentiert die Größe des Puffers
limit Puffer__Der erste INDEX, der nicht IO sein kann__
position Puffer__Der erste INDEX, der IO sein kann__
mark Die Position, die die Position zurückgibt, wenn Sie im Puffer markieren und zurücksetzen

Die obigen vier Faktoren erfüllen die folgenden Anforderungen 0 <= mark <= position <= limit <= capacity

Regelmäßige Unterklasse von Buffer

  1. ByteBuffer ist gesetzt / get
  2. ByteBuffer wird gesetzt / abgerufen

Die reguläre Methode von Buffer

Methode Erläuterung Implementierung von CharBuffer
Buffer flip() Bereiten Sie die Ausgabe vor limit = position
positon = 0
mark = -1
int capacity() Rückgabe der Pufferkapazität return capacity
int limit() Rückgabe des Pufferlimits return limit
int position() Pufferposition zurückgegeben return position
int remaining() Anzahl der Elemente zwischen Position und Grenze return limit - position
boolean hasRemaining() Gibt es ein Element zwischen Position und Grenze? return position < limit
Buffer position(int newPostion) Position setzen Abkürzung
Buffer mark() An der aktuellen Position markieren mark = position
return this
Buffer reset() Position zur Markierung zurückbringen int m = mark
if (m < 0)
throw new InvalidMarkException()
position = m
return this
Buffer rewind() Bewegen Sie die Position zurück zum oberen Rand des Puffers und brechen Sie die Markierung ab position = 0
mark = -1
return this
Buffer clear() Puffer Zurück zum Ausgangszustand position = 0
limit = capacity
mark = -1
return this

CharBuffer-Beispiel

Ausgabemethode


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());
}

Generieren


CharBuffer buffer = CharBuffer.allocate(8);
System.out.println("-----Nach der Generation-----");
showProperty(buffer);

Ausgabe ----- Nach der Generation ----- 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.Das Ende des Puffers ist 8
2.IO Startposition(position)ist 0
3. toString()Ist die Position~Da es sich um ein Limit handelt, 8 Nullen


#### **`put()`**
```java

buffer.put('a');
buffer.put('b');
buffer.put('c');
 System.out.println ("----- After put -----");
showProperty(buffer);
 ----- Nach dem Put -----
capacity : 8
limit : 8
position : 3
toString() :      

Buffer-put.png

  1. put()Ich habe es dreimal gemacht, also die Position+3
  2. toString()Ist die Position~Da es sich um ein Limit handelt, 5 Nullen

flip()


buffer.flip();
 System.out.println ("----- nach dem Umdrehen -----");
showProperty(buffer);
 ----- Nach dem Umdrehen -----
capacity : 8
limit : 3
position : 0
toString() : abc

Buffer-flip.png 1.Erster INDEX, der nicht IO sein kann(limit)Ist 3 2.Der erste INDEX, der IO sein kann(position)Startposition ist 0 3. toString()Ist die Position~Weil es eine Grenze istabc

get()


buffer.get();
buffer.get();
System.out.println("-----get-----");
showProperty(buffer);
 ----- Nach get -----
capacity : 8
limit : 3
position : 2
toString() : c

Buffer-get.png

  1. get()Da es zweimal ist, ist die Position+2、cZeigen auf
    1. toString()Ist die Position~Weil es eine Grenze istc

clear()


buffer.clear();
 System.out.println ("----- nach Löschen -----");
showProperty(buffer);
System.out.println("get(2) : " + buffer.get(2));
 ----- Nach dem Löschen -----
capacity : 8
limit : 8
position : 0
toString() : abc     
get(2) : c

Buffer-clear.png 1.Da es zur Ausgangsposition zurückkehrt, Position=0, limit,capacity=8 2.Hier nicht gezeigt, aber markieren=-1 3. clear()Geben Sie einfach die Position zurück__Weil es den Puffer nicht löscht__、 clear()Holen Sie sich auch nach(2)damitcが取得damitきる

###Bonus ByterBuffer hat allocateDirect()Es gibt eine Methode, mit der eine Instanz abgerufen werden kann. Die E / A-Effizienz ist hoch, aber die Produktionskosten sind hoch, sodass sie nicht für den Einweggebrauch geeignet sind.

Channel

Direkten Kontakt(Festplatte, Netz usw.)Es ist eine Pipe, die mit und allen E / A verbunden ist__Durch Puffer__Machen.

IO-Methode Erläuterung
Channel#map Stellen Sie den Bereich der Start- und Endpositionen in Buffer
Position lesen(Channel.position)Nicht aufnehmen
Channel#read Puffer vom Kanal einfügen
Notieren Sie die Leseposition
Channel#write Kanal aus Puffer einfügen
Notieren Sie die Schreibposition

channel-img.png

###Teilweise Implementierung von Channel

FileChannel

map(), write()

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

*Kartenverarbeitung * getChannel() ->FileChannel-Instanziierung * 0, f.length() -> 0~Holen Sie sich 15 Bytes * buffer position : 0 -> flip()Erledigt * channel position -?Halten Sie die Leseposition nicht in der Datei

read()

File 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 ("---- Kanal # 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 ("---- Kanal # 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());
}
 ---- Kanal # 1. Mal gelesen ----
buffer capacity : 8
buffer limit : 8
buffer position : 8
channel position : 8
hasRead : 8
 ---- Kanal # 2. Mal gelesen ----
buffer capacity : 8
buffer limit : 8
buffer position : 7
channel position : 15
hasRead : 7

*1. Mal lesen * buffer position : 8 ->8 Bytes gelesen * channel position : 8 ->Als nächstes folgt der Dateiindex= 8(9. Byte)Lesen Sie aus *2. Mal lesen * buffer position : 7 ->7 Bytes gelesen * channel position : 15 ->Als nächstes folgt der Dateiindex= 15(9. Byte)Lesen Sie aus

Charset

Java verwendet standardmäßig Unicode, aber beim Lesen anderer Zeichencodes können verstümmelte Zeichen auftreten. Der Zeichensatz dient zum Konvertieren von Byte und Zeichen.

IO-Methode Erläuterung
CharBuffer Charset#decode(ByteBuffer buf) ByteBuffer to CharBuffer
ByteBuffer Charset#encode(CharBuffer buf) CharBuffer to ByteBuffer
ByteBuffer Charset#encode(String str) String to ByteBuffer

###Zeichensatz wird von Java unterstützt

Charset.availableCharsets()


 // Zeichensatzliste
Charset.availableCharsets().entrySet().forEach(System.out::println);

// defalut
System.out.println("default charset : " + Charset.defaultCharset()); // UTF-8

Teil


 ・ ・ ・ Abkürzung
Shift_JIS=Shift_JIS
UTF-16=UTF-16
UTF-32=UTF-32
UTF-8=UTF-8
 ・ ・ ・ Abkürzung

ByteBuffer to CharBuffer

SJIS-Datei lesen


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 to ByteBuffer

String(unicode)Ist in SJIS geschrieben


try (
    FileChannel outChannel = new FileOutputStream("./NIO/file-sjis-out.txt").getChannel()) {

    // unicode
 String 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());
}

Oder

Es ist auch in String! !!


new String(byte[] xx, "Shift_JIS");

###Ein unklarer Punkt utf-8(1byte ~ 6byte)Wenn die Anzahl der Bytes je nach Zeichen unterschiedlich ist, z Was soll ich mit der Puffergröße machen? ?? ??

UTF-8 Dateien


 ab ai

ab = 2byte Ai= 3byte + 3byte

ByteBuffer byteBuffer = ByteBuffer.allocate(6)Wenn eingestellt auf ab ah + 1. ByteGeht in den Puffer und dekodiertab ah�werden.

Was soll ich in diesem Fall tun? ?? ??

  1. ~~Verwenden Sie das gemeinsame Vielfache des Zeichensatzes.~~ ~~「1,2,3,4,5,Da es "6" ist, verwenden Sie ein Vielfaches von 60 Bytes als Puffergröße.~~

2.Bestimmen Sie verstümmelte Zeichen, setzen Sie sie an den Anfang von Buffer, passen Sie die Position an und lesen Sie. ⇒ map()Blocklesen & Dateiposition nicht beibehalten! ~~Muss ich eine Größe angeben, die nicht verstümmelt? ??~~

Die Lösung ist unten.

Steuerung Erläuterung
onMalformedInput Unzulässiger Eingabefehler
onUnmappableCharacter Nicht zugeordneter Zeichenfehler
Art Erläuterung
CodingErrorAction.IGNORE Fehlerzeichen ignorieren
CodingErrorAction.REPLACE Fehler beim Ersetzen von Zeichen
CodingErrorAction.REPORT Fehlermeldung

CodingErrorAction.IGNORE

IGNORE Probe


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) {
 // IO-Vorbereitung
        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());
}

Ausgabe


 ab ah

ichWurde ignoriert

CodingErrorAction.IGNORE

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) {
 // IO-Vorbereitung
        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());
}

Ausgabe


 ab Aoo

ich1. Byte ⇒ ich2. Byte ⇒ ich3. Byte ⇒

CodingErrorAction.REPORT

IGNORE,REPLACE zerstört die Originaldaten !!

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);

 // Ausgabe
            System.out.print(charBuffer.toString());
            byteBuffer.clear();
        } catch (MalformedInputException ex) {
 // Fehlerauftrittsposition und Endposition
            int errorIndexStart = byteBuffer.position();
            int errorIndexEnd = byteBuffer.limit();

 // Ausgabe in normale Position
            byteBuffer.flip();
            CharBuffer charBuffer = decoder
                .decode(byteBuffer);
            System.out.print(charBuffer.toString());

 // Verschiebe den Anfang bis zum Ende der Fehlerposition an den Anfang des Puffers
            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.Wenn ein Fehler auftritt, wird zuerst an die normale Position ausgegeben. 2.Bewegen Sie sich von der Position des Auftretens des Fehlers zum Ende des Puffers 3.Der nächste Lesevorgang erfolgt nach der Fehlerlänge, nicht ab 0 4. utf-8 ist 1 bis 6 Bytes, also ordnen Sie mindestens zu(6)Brauchst du?

Ist das wirklich das Beste? ??

FileLock

Stellt eine Sperre für eine Datei dar

FileChannel-Sperrmethode Erläuterung
FileChannel#lock() lock(0L, Long.MAX_VALUE, false)
FileChannel#lock(long position, long size, boolean shared) Sperrbereich, gemeinsame Sperre, exklusive Sperre können angegeben werden
FileChannel#tryLock() tryLock(0L, Long.MAX_VALUE, false)
FileChannel#tryLock(long position, long size, boolean shared) Sperrbereich, gemeinsame Sperre, exklusive Sperre können angegeben werden

lock()Und tryLock()Der Unterschied von

lock()Blockiert Threads bis zur Sperrenerfassung. tryLock gibt null zurück, wenn die Sperre nicht erreicht werden kann.

lock()

Probe sperren


try (FileChannel fileChannel = new FileOutputStream("file-lock-out.txt").getChannel();) {
    FileLock lock = fileChannel.lock();
 System.out.println ("Sperre wurde erhalten");
 System.out.println ("Sperre 60 Sekunden lang halten");
    Thread.sleep(60 * 1000);
    lock.release();
} catch (IOException | InterruptedException ex) {
    System.out.println("1" + ex.getMessage());
}

Wenn das oben genannte zweimal mit verschiedenen jvm ausgeführt wird

Ausgabe von jvm1


 Ich konnte das Schloss bekommen
 Halten Sie die Sperre für 60 Sekunden

Es erfolgt keine Ausgabe, da die Ausgabe von jvm2 wartet.

tryLock()

tryLock()Stichprobe


try (FileChannel fileChannel = new FileOutputStream("file-lock-out.txt").getChannel();) {
    FileLock lock = fileChannel.tryLock();
    if (lock != null) {
 System.out.println ("tryLock wurde erworben");
        Thread.sleep(60 * 1000);
        lock.release();
    } else {
        System.out.println("lock is null");
    }
} catch (IOException | InterruptedException ex) {
    System.out.println(ex.getMessage());
}

jvm1 Ausgabe


 Ich konnte tryLock bekommen

jvm2 Ausgabe


lock is null

###Andere 1.Da die Sperre jvm gehört, können Sie nicht dieselbe Datei mit derselben jvm sperren. 2.Auf einigen Plattformen wird die Sperre aufgehoben, wenn der FileChannel geschlossen wird. Es ist also nicht gut, mehrere FileChannels für gesperrte Dateien zu öffnen. 3.Auf einigen Plattformen werden Dateisperren empfohlen und sind nicht obligatorisch. ⇒ Sie können ohne Sperre lesen und schreiben.

#Als nächstes kommt NIO.2 https://qiita.com/liguofeng29/items/3d0ba350a1547630727b

Recommended Posts

NIO.2 Überprüfung von Java
NIO Bewertung von Java
Bewertung von Java Shilber
Überprüfungshinweise zu Java NIO 2
Java-Überprüfung
Java IO Bewertung
[Java] Übersicht über Java
Abgelaufene Java-Sammlung
Voraussichtliche Funktionen von Java
[Java] Bedeutung der serialVersionUID
Java - Vereinigung von Kommentaren
Überprüfung der Java-Innenklasse
Java (Verdienste des Polymorphismus)
Ein kurzer Überblick über Java, das im Unterricht gelernt wurde
Überprüfen Sie jetzt die Java-Anmerkungen
Überprüfen Sie java8 ~ Lambda Typ ~
[Java] Drei Funktionen von Java
Zusammenfassung der Java-Unterstützung 2018
Java-Überprüfung ③ (grundlegende Verwendung von Arrays / Referenztyp)
Ein kurzer Überblick über Java, das in Klasse 4 gelernt wurde
[Java] Über Objects.equals () und Überprüfung des String-Vergleichs (== und gleich)
Ein kurzer Überblick über Java, das in Klasse 3 gelernt wurde
Ein kurzer Überblick über Java, das in Klasse 2 gelernt wurde
Über Java-Instanzen
[Java] Mirage-Basic-Verwendung von SQL
[Java] Anfängerverständnis von Servlet-②
[Java] Praxis der Ausnahmebehandlung [Ausnahme]
[Java11] Stream-Zusammenfassung - Vorteile von Stream -
Progate Java (Anfänger) Review & Zusammenfassung
[Java] Erstellen von Originalanmerkungen
[Java] Anfängerverständnis von Servlet-①
Java Ende des Monats plusMonate
[Java] Zusammenfassung der regulären Ausdrücke
[Java] Zusammenfassung der Operatoren (Operator)
[Java] Implementierung des Faistel-Netzwerks
[Java] Komparator der Collection-Klasse
Zusammenfassung der Grundlagen der Java-Sprache
Zusammenfassung der Java Math Klasse
Aufzählung aller Kombinationen Java
Java (Vererbung von is-ein Prinzip)
Vor- und Nachteile von Java
Vorteile der statischen Java-Methode
[Java] Zusammenfassung der Steuerungssyntax
Java-Implementierung von Tri-Tree
Zusammenfassung der Java-Fehlerverarbeitung
[Java] Zusammenfassung der Entwurfsmuster
[Java] Zusammenfassung der mathematischen Operationen
Denken Sie an eine Java-Update-Strategie
[Java] Löschen Sie die Elemente von List
[Für Anfänger] Zusammenfassung des Java-Konstruktors
Verschiedene Methoden der Java String Klasse
Grundursache für Java Framework Bug
Über Biocontainer fastqc und Java
[Java Edition] Geschichte der Serialisierung
Zusammenfassung des Pakets [Java Silver Study]
Über Lambda, Stream, LocalDate von Java8
Extraktion von "Ruby" Double Hash * Review
Die Geschichte von Java Gold SE8
Liste der Java-Objekte sortieren