Ich wurde schon zweimal in Interviews gefragt, wie man Dateien liest und ausgibt. Damals konnte ich mich nur an eine grobe Idee erinnern. Heute habe ich diesen Aspekt speziell zusammengefasst unten und teile es mit allen.
Zuallererst gibt es drei häufig verwendete Dateilese- und Ausgabestreams: FileInputStream/FileOutputStream, FileReader/FileWriter und RandomAccessFile. Hier einige einfache Beispiele als Referenz:
Grundlagen:
1.
FileRead fr = new FileReader(filename); String s; while( (s=fr.readLine())!=null){ ... } fr.close(); //FileWriter同理,输出时可用write()函数 //Java I/O中所有的Reader、Writer都是面向字符流的输出输出
2.
FileInputStream fi =new FileInputStream(filename); int in; while( (in=fi.read())!=-1){ ... } fi.close(); //FileOutputStream同理 //Java I/O中所有的Reader、Writer都是面向字节流的输出输出
3.
RandomAccessFile ra =new RandomAccessFile(filename,"rw");//后面的参数指定的是 打开文件流的方式,“rw”是指读写,“r”是只读,Java不提供只写 ra.seek(number);//将文件指针移动到number处,这里文件指针可以理解为文件开始读的位置 ra.skipByte(number);//跳过number个字节 ra.read(); ra.close(); //RandomAccessFile既可以读也可以写,而且可以利用seek()函数指定位置
Das Folgende ist eine Einführung aus der Baidu-Enzyklopädie:
RandomAccessFile gehört nicht zu den Kategorien InputStream und OutputStream. Abgesehen von der Implementierung der DataInput- und DataOutput-Schnittstellen (DataInputStream und DataOutputStream implementieren auch diese beiden Schnittstellen) hat es nichts mit diesen beiden Klassen zu tun und verwendet nicht einmal die von InputStream und OutputStream vorbereiteten Funktionen völlig unabhängige Klasse, alle Methoden (von denen die meisten zu sich selbst gehören) werden von Grund auf neu geschrieben. Dies kann daran liegen, dass RandomAccessFile sich innerhalb der Datei vorwärts und rückwärts bewegen kann und sich sein Verhalten daher grundlegend von anderen E/A-Klassen unterscheidet. Alles in allem handelt es sich um eine unabhängige Klasse, die Object direkt erbt.
Erweiterter Artikel:
In nio implementiert Java den I/O-Stream neu und führt einige neue Methoden zur Verbesserung der Geschwindigkeit ein. Ich führe hauptsächlich Kanäle und speicherzugeordnete Dateien ein
1. Kanäle:
Ein Beispiel in Thinking in Java ist besonders leicht zu verstehen: Wir setzen, was wir wollen Die gelesene Datei wird als Kohlenmine betrachtet, und die Daten sind die Kohle, die wir wollen. Der Kanal ist wie ein Förderband, das die Kohle direkt vom Förderband transportiert, daher müssen wir die Kohle mit Lastwagen verladen. Er ist hauptsächlich für den Abtransport zuständig Daten vom Kanal und Übergabe an das von uns geschriebene Programm. Der einzige Puffer, der mit Kanälen interagieren kann, ist ByteBuffer. Es ist ersichtlich, dass die Methode zum Parsen von Streams, die von Kanälen unterstützt werden, Byte-Streams sind. Es verwendet also FileInputStream/FileOutputStream, RandomAccessFile
Beispiel:
a.
FileChannel fc =new FileOutputStream(filename).getChannel(); fc.write(ByteBuffer.wrap("something test".getBytes() ));//这里使用ByteBuffer比较简单,其实ByteBuffer可以利用个put()函数写入byte数组 fc.close();
b.
fc= new FileOutputStream(filename).getChannel(); ByteBuffer buff = ByteBuffer.allocate(size);//没错,ByteBuffer是不提供显示构造函数的,想要新建一个对象必须利用allocate()函数来分配空间。 fc.read(buff); fc.close();
Warum denken Sie darüber? ? Was ist mit der Verwendung von Kanälen für E/A? Der Hauptaspekt ist die Leistung. Kanäle und Puffer können es Programmen ermöglichen, eine bestimmte Anzahl von Zeichen zu lesen und zu schreiben, aber wenn nur InputStream/OutputStream verwendet wird, kann Reader/Writer nur ein Byte lesen und schreiben eine Zeit/ein Charakter. Wenn das Programm E/A ausführt, muss es an das Betriebssystem übergeben werden, um diesen Teil der Funktion zu lösen (Aufruf von Systemaufrufen). Durch die Reduzierung der Anzahl der Übergaben an das Betriebssystem kann die für E/A aufgewendete Zeit effektiv reduziert werden. O
2. Speicherzuordnungsdatei:
Die Hauptbedeutung der Speicherzuordnungsdatei besteht tatsächlich darin, davon auszugehen, dass die Dateien als sehr großes Array im Speicher abgelegt und darauf zugegriffen wird, was sehr effizient ist. Warum ist es besser? Das beginnt mit der Java Virtual Machine und dem Betriebssystem (Eigentlich verstehe ich es nicht sehr gut. Ich habe gerade einen Artikel gelesen, der es klar erklärt. Der Link ist http://www.360doc.com/ Inhalt ...) In diesem Artikel werden hauptsächlich die Prinzipien von Java I/O und die Prinzipien von speicherzugeordneten Dateien vorgestellt. Lassen Sie mich zusammenfassen: Die Hauptimplementierungsmethode von Java I/O besteht definitiv darin, Systemaufrufe zu verwenden, und die Systemaufrufe übertragen zunächst die Dateien, die Sie verwenden möchten, von der Festplatte in den E/A-Puffer des Kernels , Sie möchten mehr Inhalt in die Datei importieren (das Kopieren von mehr Inhalt erfolgt aufgrund des Lokalitätsprinzips des Programms, wodurch eine bessere Effizienz erzielt werden kann) und importieren ihn dann aus dem E/A-Puffer des Kernels in Java Der eigene private Speicherbereich des Prozesses. Die speicherzugeordnete Datei gibt die Methode der zwei Kopien auf und erstellt direkt eine Zuordnung zwischen dem virtuellen Raum des Java-Prozesses und dem Dateiobjekt. Wenn der gewünschte Inhalt nicht im privaten Speicherbereich gefunden werden kann, tritt eine Seitenfehlerausnahme auf Um dieses Problem zu lösen, wird ein Systemaufruf auf niedrigerer Ebene verwendet (tatsächlich ist auch die Behandlung von Seitenfehlern an E/A-Systemaufrufen beteiligt. Der Vorteil besteht darin, dass der Overhead vom Kernel-E/A-Puffer zum privaten Prozess reduziert wird). Adresse.
Beispiel:
FileChannel fc = new RandomAccessFile(filename,"rw").getChannel(); MappedByteBuffer mb = fc.map(FileChannel.MapMode.READ_WRITE,start,length); mb.put((byte)'x'); mb.get(); fc.close();
Als ich das schrieb, fielen mir plötzlich die vier Möglichkeiten ein, „Fenchel“ in „Kong Yiji“ zu schreiben. Jetzt gibt es mindestens fünf Möglichkeiten, Dateien in Java zu öffnen , jede Art hat ihre eigenen Vor- und Nachteile. Von nun an können Sie auch eine Robe tragen und andere fragen, ob Sie die 5 Möglichkeiten kennen, Dateien in Java zu lesen und zu schreiben